blob: 446980f701f84f5d240989057baaf7cabed868ed [file] [log] [blame]
# 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.
# Templatated tests with eval/arguments/future reserved words.
# ----------------------------------------------------------------------
# Constants and utility functions
reserved_words = [
'class',
'const', # Has other error message than other reserved words.
'enum',
'export',
'extends',
'import',
'super'
]
strict_reserved_words = [
'implements',
'interface',
'let',
'package',
'private',
'protected',
'public',
'static',
'yield'
]
assign_ops = {
"=": "assign",
"+=": "addeq",
"-=": "subeq",
"*=": "muleq",
"/=": "diveq",
"%=": "modeq",
"&=": "andeq",
"|=": "oreq",
"^=": "xoreq",
"<<=": "shleq",
">>=": "asreq",
">>>=": "lsreq"
}
# A template that performs the same strict-mode test in different
# scopes (global scope, function scope, and nested function scope).
def StrictTemplate(name, source):
def MakeTests(replacement, expectation):
Template(name, '"use strict";\n' + source)(replacement, expectation)
Template(name + '-infunc',
'function foo() {\n "use strict";\n' + source +'\n}\n')(
replacement, expectation)
Template(name + '-infunc2',
'function foo() {\n "use strict";\n function bar() {\n' +
source +'\n }\n}\n')(replacement, expectation)
return MakeTests
# ----------------------------------------------------------------------
# Test templates
arg_name_own = Template("argument-name-own-$id", """
function foo($id) {
"use strict";
}
""")
arg_name_nested = Template("argument-name-nested-$id", """
function foo() {
"use strict";
function bar($id) { }
}
""")
func_name_own = Template("function-name-own-$id", """
function $id(foo) {
"use strict";
}
""")
func_name_nested = Template("function-name-nested-$id", """
function foo() {
"use strict";
function $id(bar) { }
}
""")
catch_var = StrictTemplate("catch-$id", """
try { } catch ($id) { }
""")
declare_var = StrictTemplate("var-$id", """
var $id = 42;
""")
assign_var = StrictTemplate("assign-$id-$opname", """
var x = $id $op 42;
""")
prefix_var = StrictTemplate("prefix-$opname-$id", """
var x = $op$id;
""")
postfix_var = StrictTemplate("postfix-$opname-$id", """
var x = $id$op;
""")
read_var = StrictTemplate("read-reserved-$id", """
var x = $id;
""")
setter_arg = StrictTemplate("setter-param-$id", """
var x = {set foo($id) { }};
""")
label_normal = Template("label-normal-$id", """
$id: '';
""")
label_strict = StrictTemplate("label-strict-$id", """
$id: '';
""")
break_normal = Template("break-normal-$id", """
$id: for (;false;) {
break $id;
}
""")
break_strict = StrictTemplate("break-strict-$id", """
$id: for (;false;) {
break $id;
}
""")
continue_normal = Template("continue-normal-$id", """
$id: for (;false;) {
continue $id;
}
""")
continue_strict = StrictTemplate("continue-strict-$id", """
$id: for (;false;) {
continue $id;
}
""")
non_strict_use = Template("nonstrict-$id", """
var $id = 42;
$id++;
$id--;
++$id;
--$id;
$id += 10;
$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++;
$id--;
++$id;
--$id;
$id += 10;
$id -= 10;
try {} catch ($id) { }
function $id($id) { }
x = {$id: 42};
x = {get $id() {}, set $id(value) {}};
$id: '';
""")
identifier_name_source = """
var x = {$id: 42};
x = {get $id() {}, set $id(value) {}};
x.$id = 42;
function foo() { "use strict;" }
x = {$id: 42};
x = {get $id() {}, set $id(value) {}};
x.$id = 42;
"""
identifier_name = Template("identifier_name-$id", identifier_name_source)
identifier_name_strict = StrictTemplate("identifier_name_strict-$id",
identifier_name_source)
# ----------------------------------------------------------------------
# Run tests
# eval and arguments have specific exceptions for different uses.
for id in ["eval", "arguments"]:
arg_name_own({"id": id}, "strict_param_name")
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")
catch_var({"id": id}, "strict_catch_variable")
declare_var({"id": id}, "strict_var_name")
prefix_var({"id": id, "op":"++", "opname":"inc"}, "strict_lhs_prefix")
prefix_var({"id": id, "op":"--", "opname":"dec"}, "strict_lhs_prefix")
postfix_var({"id": id, "op":"++", "opname":"inc"}, "strict_lhs_postfix")
postfix_var({"id": id, "op":"--", "opname":"dec"}, "strict_lhs_postfix")
label_normal({"id": id}, None)
label_strict({"id": id}, None)
break_normal({"id": id}, None)
break_strict({"id": id}, None)
continue_normal({"id": id}, None)
continue_strict({"id": id}, None)
non_strict_use({"id": id}, None)
# Reserved words just throw the same exception in all cases
# (with "const" being special, as usual).
for reserved_word in reserved_words + strict_reserved_words:
if (reserved_word in strict_reserved_words):
message = "strict_reserved_word"
label_message = None
elif (reserved_word == "const"):
message = "unexpected_token"
label_message = message
else:
message = "reserved_word"
label_message = message
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():
assign_var({"id":reserved_word, "op":op, "opname": assign_ops[op]}, message)
catch_var({"id":reserved_word}, message)
declare_var({"id":reserved_word}, message)
prefix_var({"id":reserved_word, "op":"++", "opname":"inc"}, message)
prefix_var({"id":reserved_word, "op":"--", "opname":"dec"}, message)
postfix_var({"id":reserved_word, "op":"++", "opname":"inc"}, message)
postfix_var({"id":reserved_word, "op":"--", "opname":"dec"}, message)
read_var({"id": reserved_word}, message)
identifier_name({"id": reserved_word}, None);
identifier_name_strict({"id": reserved_word}, None);
label_normal({"id": reserved_word}, label_message)
break_normal({"id": reserved_word}, label_message)
continue_normal({"id": reserved_word}, label_message)
if (reserved_word == "const"):
# The error message for this case is different because
# ParseLabelledStatementOrExpression will try to parse this as an expression
# first, effectively disallowing the use in ParseVariableDeclarations, i.e.
# the preparser never sees that 'const' was intended to be a label.
label_strict({"id": reserved_word}, "strict_const")
else:
label_strict({"id": reserved_word}, message)
break_strict({"id": reserved_word}, message)
continue_strict({"id": reserved_word}, message)
# Future reserved words in strict mode behave like normal identifiers
# in a non strict context.
for reserved_word in strict_reserved_words:
non_strict_use({"id": reserved_word}, None)