Make "native" not a keyword.

We now only recognize "native function" when it occurs in extension scripts
(parsing with a non-NULL extension), and only if there is no line-terminator
between "native" and "function" (so that it would otherwise be a Syntax Error).
Preparsing never recognizes native functions, which is acceptable since we
never preparse extension scripts (because we don't allow lazy functions
anyway).

BUG=v8:1097

Review URL: http://codereview.chromium.org/7206020

git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@8326 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
This commit is contained in:
lrn@chromium.org 2011-06-20 10:20:57 +00:00
parent b789cb8c94
commit 480ec43c4e
10 changed files with 32 additions and 59 deletions

View File

@ -159,6 +159,7 @@ inline Heap* _inline_get_heap_();
V(function_symbol, "function") \
V(length_symbol, "length") \
V(name_symbol, "name") \
V(native_symbol, "native") \
V(number_symbol, "number") \
V(Number_symbol, "Number") \
V(nan_symbol, "NaN") \

View File

@ -1269,9 +1269,6 @@ Statement* Parser::ParseStatement(ZoneStringList* labels, bool* ok) {
return ParseFunctionDeclaration(ok);
}
case Token::NATIVE:
return ParseNativeDeclaration(ok);
case Token::DEBUGGER:
stmt = ParseDebuggerStatement(ok);
break;
@ -1392,13 +1389,6 @@ VariableProxy* Parser::Declare(Handle<String> name,
// declaration is resolved by looking up the function through a
// callback provided by the extension.
Statement* Parser::ParseNativeDeclaration(bool* ok) {
if (extension_ == NULL) {
ReportUnexpectedToken(Token::NATIVE);
*ok = false;
return NULL;
}
Expect(Token::NATIVE, CHECK_OK);
Expect(Token::FUNCTION, CHECK_OK);
Handle<String> name = ParseIdentifier(CHECK_OK);
Expect(Token::LPAREN, CHECK_OK);
@ -1751,7 +1741,7 @@ Statement* Parser::ParseExpressionOrLabelledStatement(ZoneStringList* labels,
// Identifier ':' Statement
bool starts_with_idenfifier = peek_any_identifier();
Expression* expr = ParseExpression(true, CHECK_OK);
if (peek() == Token::COLON && starts_with_idenfifier && expr &&
if (peek() == Token::COLON && starts_with_idenfifier && expr != NULL &&
expr->AsVariableProxy() != NULL &&
!expr->AsVariableProxy()->is_this()) {
// Expression is a single identifier, and not, e.g., a parenthesized
@ -1781,6 +1771,19 @@ Statement* Parser::ParseExpressionOrLabelledStatement(ZoneStringList* labels,
return ParseStatement(labels, ok);
}
// If we have an extension, we allow a native function declaration.
// A native function declaration starts with "native function" with
// no line-terminator between the two words.
if (extension_ != NULL &&
peek() == Token::FUNCTION &&
!scanner().has_line_terminator_before_next() &&
expr != NULL &&
expr->AsVariableProxy() != NULL &&
expr->AsVariableProxy()->name()->Equals(
isolate()->heap()->native_symbol())) {
return ParseNativeDeclaration(ok);
}
// Parsed expression statement.
ExpectSemicolon(CHECK_OK);
return new(zone()) ExpressionStatement(expr);
@ -4982,6 +4985,7 @@ bool ParserApi::Parse(CompilationInfo* info) {
Parser parser(script, true, NULL, NULL);
result = parser.ParseLazy(info);
} else {
// Whether we allow %identifier(..) syntax.
bool allow_natives_syntax =
info->allows_natives_syntax() || FLAG_allow_natives_syntax;
ScriptDataImpl* pre_data = info->pre_parse_data();

View File

@ -209,9 +209,6 @@ PreParser::Statement PreParser::ParseStatement(bool* ok) {
case i::Token::FUNCTION:
return ParseFunctionDeclaration(ok);
case i::Token::NATIVE:
return ParseNativeDeclaration(ok);
case i::Token::DEBUGGER:
return ParseDebuggerStatement(ok);
@ -246,29 +243,6 @@ PreParser::Statement PreParser::ParseFunctionDeclaration(bool* ok) {
}
// Language extension which is only enabled for source files loaded
// through the API's extension mechanism. A native function
// declaration is resolved by looking up the function through a
// callback provided by the extension.
PreParser::Statement PreParser::ParseNativeDeclaration(bool* ok) {
Expect(i::Token::NATIVE, CHECK_OK);
Expect(i::Token::FUNCTION, CHECK_OK);
ParseIdentifier(CHECK_OK);
Expect(i::Token::LPAREN, CHECK_OK);
bool done = (peek() == i::Token::RPAREN);
while (!done) {
ParseIdentifier(CHECK_OK);
done = (peek() == i::Token::RPAREN);
if (!done) {
Expect(i::Token::COMMA, CHECK_OK);
}
}
Expect(i::Token::RPAREN, CHECK_OK);
Expect(i::Token::SEMICOLON, CHECK_OK);
return Statement::Default();
}
PreParser::Statement PreParser::ParseBlock(bool* ok) {
// Block ::
// '{' Statement* '}'
@ -362,8 +336,9 @@ PreParser::Statement PreParser::ParseExpressionOrLabelledStatement(bool* ok) {
// Identifier ':' Statement
Expression expr = ParseExpression(true, CHECK_OK);
if (peek() == i::Token::COLON && expr.IsRawIdentifier()) {
if (!strict_mode() || !expr.AsIdentifier().IsFutureReserved()) {
if (expr.IsRawIdentifier()) {
if (peek() == i::Token::COLON &&
(!strict_mode() || !expr.AsIdentifier().IsFutureReserved())) {
Consume(i::Token::COLON);
i::Scanner::Location start_location = scanner_->peek_location();
Statement statement = ParseStatement(CHECK_OK);
@ -375,6 +350,9 @@ PreParser::Statement PreParser::ParseExpressionOrLabelledStatement(bool* ok) {
}
return Statement::Default();
}
// Preparsing is disabled for extensions (because the extension details
// aren't passed to lazily compiled functions), so we don't
// accept "native function" in the preparser.
}
// Parsed expression statement.
ExpectSemicolon(CHECK_OK);

View File

@ -373,7 +373,6 @@ class PreParser {
SourceElements ParseSourceElements(int end_token, bool* ok);
Statement ParseStatement(bool* ok);
Statement ParseFunctionDeclaration(bool* ok);
Statement ParseNativeDeclaration(bool* ok);
Statement ParseBlock(bool* ok);
Statement ParseVariableStatement(bool* ok);
Statement ParseVariableDeclarations(bool accept_IN, int* num_decl, bool* ok);

View File

@ -897,7 +897,6 @@ void KeywordMatcher::Step(unibrow::uchar input) {
if (MatchKeywordStart(input, "instanceof", 2, Token::INSTANCEOF)) return;
break;
case N:
if (MatchKeywordStart(input, "native", 1, Token::NATIVE)) return;
if (MatchKeywordStart(input, "new", 1, Token::NEW)) return;
if (MatchKeywordStart(input, "null", 1, Token::NULL_LITERAL)) return;
break;

View File

@ -1,4 +1,4 @@
// Copyright 2006-2008 the V8 project authors. All rights reserved.
// Copyright 2011 the V8 project authors. All rights reserved.
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
@ -168,7 +168,6 @@ namespace internal {
/* 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. */ \
T(ILLEGAL, "ILLEGAL", 0) \

View File

@ -253,7 +253,7 @@ TEST(StandAlonePreParser) {
"{label: 42}",
"var x = 42;",
"function foo(x, y) { return x + y; }",
"native function foo(); return %ArgleBargle(glop);",
"%ArgleBargle(glop);",
"var x = new new Function('this.x = 42');",
NULL
};

View File

@ -105,7 +105,7 @@ assertFalse(a.a.b === b.a.b);
assertFalse(a.a.c === b.a.c);
// Test keywords valid as property names in initializers and dot-access.
// Test keywords are valid as property names in initializers and dot-access.
var keywords = [
"break",
"case",
@ -124,7 +124,6 @@ var keywords = [
"if",
"in",
"instanceof",
"native",
"new",
"null",
"return",
@ -137,7 +136,7 @@ var keywords = [
"var",
"void",
"while",
"with",
"with"
];
function testKeywordProperty(keyword) {

View File

@ -466,10 +466,6 @@ js1_5/extensions/regress-356378: FAIL_OK
js1_5/extensions/regress-452178: FAIL_OK
# 'native' *is* a keyword in V8.
js1_5/Regress/regress-240317: FAIL_OK
# Requires Mozilla-specific strict mode or options() function.
ecma_3/Object/8.6.1-01: FAIL_OK
js1_5/Exceptions/regress-315147: FAIL_OK

View File

@ -89,22 +89,20 @@ S7.8.4_A7.4_T1: FAIL_OK
S7.8.4_A4.3_T5: FAIL_OK
S7.8.4_A7.2_T5: FAIL_OK
# We allow some keywords to be used as identifiers
S7.5.3_A1.26: FAIL_OK
S7.5.3_A1.18: FAIL_OK
S7.5.3_A1.27: FAIL_OK
# We allow some keywords to be used as identifiers.
S7.5.3_A1.5: FAIL_OK
S7.5.3_A1.9: FAIL_OK
S7.5.3_A1.10: FAIL_OK
S7.5.3_A1.11: FAIL_OK
# native
S7.5.3_A1.20: FAIL_OK
S7.5.3_A1.15: FAIL_OK
S7.5.3_A1.16: FAIL_OK
S7.5.3_A1.18: FAIL_OK
S7.5.3_A1.21: FAIL_OK
S7.5.3_A1.22: FAIL_OK
S7.5.3_A1.23: FAIL_OK
S7.5.3_A1.15: FAIL_OK
S7.5.3_A1.24: FAIL_OK
S7.5.3_A1.16: FAIL_OK
S7.5.3_A1.26: FAIL_OK
S7.5.3_A1.27: FAIL_OK
# This checks for non-262 behavior
S12.6.4_A14_T1: PASS || FAIL_OK