From 480ec43c4e5cc6071c545281439e55d210d41097 Mon Sep 17 00:00:00 2001 From: "lrn@chromium.org" Date: Mon, 20 Jun 2011 10:20:57 +0000 Subject: [PATCH] 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 --- src/heap.h | 1 + src/parser.cc | 26 +++++++++++++++----------- src/preparser.cc | 34 ++++++---------------------------- src/preparser.h | 1 - src/scanner-base.cc | 1 - src/token.h | 3 +-- test/cctest/test-parsing.cc | 2 +- test/mjsunit/object-literal.js | 5 ++--- test/mozilla/mozilla.status | 4 ---- test/sputnik/sputnik.status | 14 ++++++-------- 10 files changed, 32 insertions(+), 59 deletions(-) diff --git a/src/heap.h b/src/heap.h index 8e8d8770d..4e7846d73 100644 --- a/src/heap.h +++ b/src/heap.h @@ -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") \ diff --git a/src/parser.cc b/src/parser.cc index dc669a8d4..1318dc928 100644 --- a/src/parser.cc +++ b/src/parser.cc @@ -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 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 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(); diff --git a/src/preparser.cc b/src/preparser.cc index 0f87d1054..818f02a3e 100644 --- a/src/preparser.cc +++ b/src/preparser.cc @@ -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); diff --git a/src/preparser.h b/src/preparser.h index 285cf0304..afd3bc347 100644 --- a/src/preparser.h +++ b/src/preparser.h @@ -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); diff --git a/src/scanner-base.cc b/src/scanner-base.cc index 0e10191fe..89591baa2 100644 --- a/src/scanner-base.cc +++ b/src/scanner-base.cc @@ -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; diff --git a/src/token.h b/src/token.h index a0afbc14f..930d525da 100644 --- a/src/token.h +++ b/src/token.h @@ -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) \ diff --git a/test/cctest/test-parsing.cc b/test/cctest/test-parsing.cc index 39856b676..08f117b35 100755 --- a/test/cctest/test-parsing.cc +++ b/test/cctest/test-parsing.cc @@ -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 }; diff --git a/test/mjsunit/object-literal.js b/test/mjsunit/object-literal.js index 5dcbb3bc7..3d0b33bd9 100644 --- a/test/mjsunit/object-literal.js +++ b/test/mjsunit/object-literal.js @@ -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) { diff --git a/test/mozilla/mozilla.status b/test/mozilla/mozilla.status index a748c9f4a..45911f1a6 100644 --- a/test/mozilla/mozilla.status +++ b/test/mozilla/mozilla.status @@ -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 diff --git a/test/sputnik/sputnik.status b/test/sputnik/sputnik.status index 7426ac239..2fe9418ce 100644 --- a/test/sputnik/sputnik.status +++ b/test/sputnik/sputnik.status @@ -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 -- 2.34.1