| # 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) |