From b97da904535cfe6489f93c366993550f3c6300aa Mon Sep 17 00:00:00 2001 From: "lrn@chromium.org" Date: Tue, 24 May 2011 14:02:59 +0000 Subject: [PATCH] Add tests for function statements in strict mode. Small fixes. Added test for const declaration in strict mode. TEST=preparser/strict-function-statement Review URL: http://codereview.chromium.org/6990056 git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@8041 ce2b1a6d-e550-0410-aec6-3dcde31c8c00 --- preparser/preparser-process.cc | 4 +- src/preparser.cc | 31 +++++++-- src/preparser.h | 11 +++- test/preparser/strict-const.js | 29 ++++++++ test/preparser/strict-function-statement.pyt | 99 ++++++++++++++++++++++++++++ test/preparser/strict-identifiers.pyt | 10 +++ 6 files changed, 177 insertions(+), 7 deletions(-) create mode 100644 test/preparser/strict-const.js create mode 100644 test/preparser/strict-function-statement.pyt diff --git a/preparser/preparser-process.cc b/preparser/preparser-process.cc index 0cd7a63..a19c66b 100644 --- a/preparser/preparser-process.cc +++ b/preparser/preparser-process.cc @@ -242,8 +242,8 @@ void CheckException(v8::PreParserData* data, if (expects->type != NULL) { const char* actual_message = reader.message(); if (strcmp(expects->type, actual_message)) { - fail(data, "Wrong error message. Expected <%s>, found <%s>\n", - expects->type, actual_message); + fail(data, "Wrong error message. Expected <%s>, found <%s> at %d..%d\n", + expects->type, actual_message, reader.beg_pos(), reader.end_pos()); } } if (expects->beg_pos >= 0) { diff --git a/src/preparser.cc b/src/preparser.cc index 4ee9bf2..86db379 100644 --- a/src/preparser.cc +++ b/src/preparser.cc @@ -242,7 +242,7 @@ PreParser::Statement PreParser::ParseFunctionDeclaration(bool* ok) { ReportMessageAt(location.beg_pos, location.end_pos, type, NULL); *ok = false; } - return Statement::Default(); + return Statement::FunctionDeclaration(); } @@ -278,7 +278,15 @@ PreParser::Statement PreParser::ParseBlock(bool* ok) { // Expect(i::Token::LBRACE, CHECK_OK); while (peek() != i::Token::RBRACE) { - ParseStatement(CHECK_OK); + i::Scanner::Location start_location = scanner_->peek_location(); + Statement statement = ParseStatement(CHECK_OK); + i::Scanner::Location end_location = scanner_->location(); + if (strict_mode() && statement.IsFunctionDeclaration()) { + ReportMessageAt(start_location.beg_pos, end_location.end_pos, + "strict_function", NULL); + *ok = false; + return Statement::Default(); + } } Expect(i::Token::RBRACE, ok); return Statement::Default(); @@ -357,7 +365,14 @@ PreParser::Statement PreParser::ParseExpressionOrLabelledStatement(bool* ok) { if (peek() == i::Token::COLON && expr.IsRawIdentifier()) { if (!strict_mode() || !expr.AsIdentifier().IsFutureReserved()) { Consume(i::Token::COLON); - ParseStatement(ok); + i::Scanner::Location start_location = scanner_->peek_location(); + Statement statement = ParseStatement(CHECK_OK); + if (strict_mode() && statement.IsFunctionDeclaration()) { + i::Scanner::Location end_location = scanner_->location(); + ReportMessageAt(start_location.beg_pos, end_location.end_pos, + "strict_function", NULL); + *ok = false; + } return Statement::Default(); } } @@ -486,7 +501,15 @@ PreParser::Statement PreParser::ParseSwitchStatement(bool* ok) { Expect(i::Token::DEFAULT, CHECK_OK); Expect(i::Token::COLON, CHECK_OK); } else { - ParseStatement(CHECK_OK); + i::Scanner::Location start_location = scanner_->peek_location(); + Statement statement = ParseStatement(CHECK_OK); + if (strict_mode() && statement.IsFunctionDeclaration()) { + i::Scanner::Location end_location = scanner_->location(); + ReportMessageAt(start_location.beg_pos, end_location.end_pos, + "strict_function", NULL); + *ok = false; + return Statement::Default(); + } } token = peek(); } diff --git a/src/preparser.h b/src/preparser.h index 2a2a49a..2efd53e 100644 --- a/src/preparser.h +++ b/src/preparser.h @@ -240,6 +240,10 @@ class PreParser { return Statement(kUnknownStatement); } + static Statement FunctionDeclaration() { + return Statement(kFunctionDeclaration); + } + // Creates expression statement from expression. // Preserves being an unparenthesized string literal, possibly // "use strict". @@ -263,11 +267,16 @@ class PreParser { return code_ == kUseStrictExpressionStatement; } + bool IsFunctionDeclaration() { + return code_ == kFunctionDeclaration; + } + private: enum Type { kUnknownStatement, kStringLiteralExpressionStatement, - kUseStrictExpressionStatement + kUseStrictExpressionStatement, + kFunctionDeclaration }; explicit Statement(Type code) : code_(code) {} diff --git a/test/preparser/strict-const.js b/test/preparser/strict-const.js new file mode 100644 index 0000000..91e9e39 --- /dev/null +++ b/test/preparser/strict-const.js @@ -0,0 +1,29 @@ +// 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: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following +// disclaimer in the documentation and/or other materials provided +// with the distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived +// from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +"use strict"; +const x = 42; \ No newline at end of file diff --git a/test/preparser/strict-function-statement.pyt b/test/preparser/strict-function-statement.pyt new file mode 100644 index 0000000..08c4288 --- /dev/null +++ b/test/preparser/strict-function-statement.pyt @@ -0,0 +1,99 @@ +# 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: +# +# * Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above +# copyright notice, this list of conditions and the following +# disclaimer in the documentation and/or other materials provided +# with the distribution. +# * Neither the name of Google Inc. nor the names of its +# contributors may be used to endorse or promote products derived +# from this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +# In strict mode, function declarations may only appear as source elements. + +# A template that performs the same strict-mode test in different +# scopes (global scope, function scope, and nested function scope). +def StrictTest(name, source): + Test(name, '"use strict";\n' + source, "strict_function") + Test(name + '-infunc', + 'function foo() {\n "use strict";\n' + source +'\n}\n', + "strict_function") + Test(name + '-infunc2', + 'function foo() {\n "use strict";\n function bar() {\n' + + source +'\n }\n}\n', + "strict_function") + +# Not testing with-scope, since with is not allowed in strict mode at all. + +StrictTest("block", """ + { function foo() { } } +""") + +StrictTest("try-w-catch", """ + try { function foo() { } } catch (e) { } +""") + +StrictTest("try-w-finally", """ + try { function foo() { } } finally { } +""") + +StrictTest("catch", """ + try { } catch (e) { function foo() { } } +""") + +StrictTest("finally", """ + try { } finally { function foo() { } } +""") + +StrictTest("for", """ + for (;;) { function foo() { } } +""") + +StrictTest("while", """ + while (true) { function foo() { } } +""") + +StrictTest("do", """ + do { function foo() { } } while (true); +""") + +StrictTest("then", """ + if (true) { function foo() { } } +""") + + +StrictTest("then-w-else", """ + if (true) { function foo() { } } else { } +""") + + +StrictTest("else", """ + if (true) { } else { function foo() { } } +""") + +StrictTest("switch-case", """ + switch (true) { case true: function foo() { } } +""") + +StrictTest("labeled", """ + label: function foo() { } +""") + + + diff --git a/test/preparser/strict-identifiers.pyt b/test/preparser/strict-identifiers.pyt index 20819ce..a0f4612 100644 --- a/test/preparser/strict-identifiers.pyt +++ b/test/preparser/strict-identifiers.pyt @@ -134,6 +134,10 @@ read_var = StrictTemplate("read-reserved-$id", """ var x = $id; """) +setter_arg = StrictTemplate("setter-param-$id", """ + var x = {set foo($id) { }}; +""") + non_strict_use = Template("nonstrict-$id", """ var $id = 42; $id++; @@ -144,6 +148,8 @@ non_strict_use = Template("nonstrict-$id", """ $id -= 10; try {} catch ($id) { } function $id($id) { } + var x = {$id: 42}; + x = {get $id() {}, set $id(value) {}}; function foo() { "use strict;" } var $id = 42; $id++; @@ -154,6 +160,8 @@ non_strict_use = Template("nonstrict-$id", """ $id -= 10; try {} catch ($id) { } function $id($id) { } + x = {$id: 42}; + x = {get $id() {}, set $id(value) {}}; """) # ---------------------------------------------------------------------- @@ -165,6 +173,7 @@ for id in ["eval", "arguments"]: arg_name_nested({"id": id}, "strict_param_name") func_name_own({"id": id}, "strict_function_name") func_name_nested({"id": id}, "strict_function_name") + setter_arg({"id": id}, "strict_param_name") for op in assign_ops.keys(): assign_var({"id": id, "op":op, "opname": assign_ops[op]}, "strict_lhs_assignment") @@ -184,6 +193,7 @@ for reserved_word in reserved_words + strict_reserved_words: if (reserved_word == "const"): message = "unexpected_token" arg_name_own({"id":reserved_word}, message) arg_name_nested({"id":reserved_word}, message) + setter_arg({"id": reserved_word}, message) func_name_own({"id":reserved_word}, message) func_name_nested({"id":reserved_word}, message) for op in assign_ops.keys(): -- 2.7.4