Commit b97da904 authored by lrn@chromium.org's avatar lrn@chromium.org

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
parent 6f775f2f
...@@ -242,8 +242,8 @@ void CheckException(v8::PreParserData* data, ...@@ -242,8 +242,8 @@ void CheckException(v8::PreParserData* data,
if (expects->type != NULL) { if (expects->type != NULL) {
const char* actual_message = reader.message(); const char* actual_message = reader.message();
if (strcmp(expects->type, actual_message)) { if (strcmp(expects->type, actual_message)) {
fail(data, "Wrong error message. Expected <%s>, found <%s>\n", fail(data, "Wrong error message. Expected <%s>, found <%s> at %d..%d\n",
expects->type, actual_message); expects->type, actual_message, reader.beg_pos(), reader.end_pos());
} }
} }
if (expects->beg_pos >= 0) { if (expects->beg_pos >= 0) {
......
...@@ -242,7 +242,7 @@ PreParser::Statement PreParser::ParseFunctionDeclaration(bool* ok) { ...@@ -242,7 +242,7 @@ PreParser::Statement PreParser::ParseFunctionDeclaration(bool* ok) {
ReportMessageAt(location.beg_pos, location.end_pos, type, NULL); ReportMessageAt(location.beg_pos, location.end_pos, type, NULL);
*ok = false; *ok = false;
} }
return Statement::Default(); return Statement::FunctionDeclaration();
} }
...@@ -278,7 +278,15 @@ PreParser::Statement PreParser::ParseBlock(bool* ok) { ...@@ -278,7 +278,15 @@ PreParser::Statement PreParser::ParseBlock(bool* ok) {
// //
Expect(i::Token::LBRACE, CHECK_OK); Expect(i::Token::LBRACE, CHECK_OK);
while (peek() != i::Token::RBRACE) { 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); Expect(i::Token::RBRACE, ok);
return Statement::Default(); return Statement::Default();
...@@ -357,7 +365,14 @@ PreParser::Statement PreParser::ParseExpressionOrLabelledStatement(bool* ok) { ...@@ -357,7 +365,14 @@ PreParser::Statement PreParser::ParseExpressionOrLabelledStatement(bool* ok) {
if (peek() == i::Token::COLON && expr.IsRawIdentifier()) { if (peek() == i::Token::COLON && expr.IsRawIdentifier()) {
if (!strict_mode() || !expr.AsIdentifier().IsFutureReserved()) { if (!strict_mode() || !expr.AsIdentifier().IsFutureReserved()) {
Consume(i::Token::COLON); 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(); return Statement::Default();
} }
} }
...@@ -486,7 +501,15 @@ PreParser::Statement PreParser::ParseSwitchStatement(bool* ok) { ...@@ -486,7 +501,15 @@ PreParser::Statement PreParser::ParseSwitchStatement(bool* ok) {
Expect(i::Token::DEFAULT, CHECK_OK); Expect(i::Token::DEFAULT, CHECK_OK);
Expect(i::Token::COLON, CHECK_OK); Expect(i::Token::COLON, CHECK_OK);
} else { } 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(); token = peek();
} }
......
...@@ -240,6 +240,10 @@ class PreParser { ...@@ -240,6 +240,10 @@ class PreParser {
return Statement(kUnknownStatement); return Statement(kUnknownStatement);
} }
static Statement FunctionDeclaration() {
return Statement(kFunctionDeclaration);
}
// Creates expression statement from expression. // Creates expression statement from expression.
// Preserves being an unparenthesized string literal, possibly // Preserves being an unparenthesized string literal, possibly
// "use strict". // "use strict".
...@@ -263,11 +267,16 @@ class PreParser { ...@@ -263,11 +267,16 @@ class PreParser {
return code_ == kUseStrictExpressionStatement; return code_ == kUseStrictExpressionStatement;
} }
bool IsFunctionDeclaration() {
return code_ == kFunctionDeclaration;
}
private: private:
enum Type { enum Type {
kUnknownStatement, kUnknownStatement,
kStringLiteralExpressionStatement, kStringLiteralExpressionStatement,
kUseStrictExpressionStatement kUseStrictExpressionStatement,
kFunctionDeclaration
}; };
explicit Statement(Type code) : code_(code) {} explicit Statement(Type code) : code_(code) {}
......
// 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
# 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() { }
""")
...@@ -134,6 +134,10 @@ read_var = StrictTemplate("read-reserved-$id", """ ...@@ -134,6 +134,10 @@ read_var = StrictTemplate("read-reserved-$id", """
var x = $id; var x = $id;
""") """)
setter_arg = StrictTemplate("setter-param-$id", """
var x = {set foo($id) { }};
""")
non_strict_use = Template("nonstrict-$id", """ non_strict_use = Template("nonstrict-$id", """
var $id = 42; var $id = 42;
$id++; $id++;
...@@ -144,6 +148,8 @@ non_strict_use = Template("nonstrict-$id", """ ...@@ -144,6 +148,8 @@ non_strict_use = Template("nonstrict-$id", """
$id -= 10; $id -= 10;
try {} catch ($id) { } try {} catch ($id) { }
function $id($id) { } function $id($id) { }
var x = {$id: 42};
x = {get $id() {}, set $id(value) {}};
function foo() { "use strict;" } function foo() { "use strict;" }
var $id = 42; var $id = 42;
$id++; $id++;
...@@ -154,6 +160,8 @@ non_strict_use = Template("nonstrict-$id", """ ...@@ -154,6 +160,8 @@ non_strict_use = Template("nonstrict-$id", """
$id -= 10; $id -= 10;
try {} catch ($id) { } try {} catch ($id) { }
function $id($id) { } function $id($id) { }
x = {$id: 42};
x = {get $id() {}, set $id(value) {}};
""") """)
# ---------------------------------------------------------------------- # ----------------------------------------------------------------------
...@@ -165,6 +173,7 @@ for id in ["eval", "arguments"]: ...@@ -165,6 +173,7 @@ for id in ["eval", "arguments"]:
arg_name_nested({"id": id}, "strict_param_name") arg_name_nested({"id": id}, "strict_param_name")
func_name_own({"id": id}, "strict_function_name") func_name_own({"id": id}, "strict_function_name")
func_name_nested({"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(): for op in assign_ops.keys():
assign_var({"id": id, "op":op, "opname": assign_ops[op]}, assign_var({"id": id, "op":op, "opname": assign_ops[op]},
"strict_lhs_assignment") "strict_lhs_assignment")
...@@ -184,6 +193,7 @@ for reserved_word in reserved_words + strict_reserved_words: ...@@ -184,6 +193,7 @@ for reserved_word in reserved_words + strict_reserved_words:
if (reserved_word == "const"): message = "unexpected_token" if (reserved_word == "const"): message = "unexpected_token"
arg_name_own({"id":reserved_word}, message) arg_name_own({"id":reserved_word}, message)
arg_name_nested({"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_own({"id":reserved_word}, message)
func_name_nested({"id":reserved_word}, message) func_name_nested({"id":reserved_word}, message)
for op in assign_ops.keys(): for op in assign_ops.keys():
......
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