Index: test/cctest/test-parsing.cc |
diff --git a/test/cctest/test-parsing.cc b/test/cctest/test-parsing.cc |
index dc4ddb0af63ae30ed9d1b3eae11a8bc3edc4178a..097296c757703173573a61325ae03d06eb5a64bc 100644 |
--- a/test/cctest/test-parsing.cc |
+++ b/test/cctest/test-parsing.cc |
@@ -1532,17 +1532,19 @@ void SetParserFlags(i::ParserBase<Traits>* parser, |
void TestParserSyncWithFlags(i::Handle<i::String> source, |
i::EnumSet<ParserFlag> flags, |
- ParserSyncTestResult result) { |
+ ParserSyncTestResult result, |
+ bool is_module = false) { |
i::Isolate* isolate = CcTest::i_isolate(); |
i::Factory* factory = isolate->factory(); |
uintptr_t stack_limit = isolate->stack_guard()->real_climit(); |
int preparser_materialized_literals = -1; |
int parser_materialized_literals = -2; |
+ bool test_preparser = !is_module; |
// Preparse the data. |
i::CompleteParserRecorder log; |
- { |
+ if (test_preparser) { |
i::Scanner scanner(isolate->unicode_cache()); |
i::GenericStringUtf16CharacterStream stream(source, 0, source->length()); |
i::Zone zone; |
@@ -1556,7 +1558,6 @@ void TestParserSyncWithFlags(i::Handle<i::String> source, |
&preparser_materialized_literals); |
CHECK_EQ(i::PreParser::kPreParseSuccess, result); |
} |
- |
bool preparse_error = log.HasError(); |
// Parse the data |
@@ -1567,7 +1568,11 @@ void TestParserSyncWithFlags(i::Handle<i::String> source, |
i::ParseInfo info(&zone, script); |
i::Parser parser(&info); |
SetParserFlags(&parser, flags); |
- info.set_global(); |
+ if (is_module) { |
+ info.set_module(); |
+ } else { |
+ info.set_global(); |
+ } |
parser.Parse(&info); |
function = info.literal(); |
if (function) { |
@@ -1596,7 +1601,7 @@ void TestParserSyncWithFlags(i::Handle<i::String> source, |
CHECK(false); |
} |
- if (!preparse_error) { |
+ if (test_preparser && !preparse_error) { |
v8::base::OS::Print( |
"Parser failed on:\n" |
"\t%s\n" |
@@ -1607,21 +1612,22 @@ void TestParserSyncWithFlags(i::Handle<i::String> source, |
CHECK(false); |
} |
// Check that preparser and parser produce the same error. |
- i::Handle<i::String> preparser_message = |
- FormatMessage(log.ErrorMessageData()); |
- if (!i::String::Equals(message_string, preparser_message)) { |
- v8::base::OS::Print( |
- "Expected parser and preparser to produce the same error on:\n" |
- "\t%s\n" |
- "However, found the following error messages\n" |
- "\tparser: %s\n" |
- "\tpreparser: %s\n", |
- source->ToCString().get(), |
- message_string->ToCString().get(), |
- preparser_message->ToCString().get()); |
- CHECK(false); |
+ if (test_preparser) { |
+ i::Handle<i::String> preparser_message = |
+ FormatMessage(log.ErrorMessageData()); |
+ if (!i::String::Equals(message_string, preparser_message)) { |
+ v8::base::OS::Print( |
+ "Expected parser and preparser to produce the same error on:\n" |
+ "\t%s\n" |
+ "However, found the following error messages\n" |
+ "\tparser: %s\n" |
+ "\tpreparser: %s\n", |
+ source->ToCString().get(), message_string->ToCString().get(), |
+ preparser_message->ToCString().get()); |
+ CHECK(false); |
+ } |
} |
- } else if (preparse_error) { |
+ } else if (test_preparser && preparse_error) { |
v8::base::OS::Print( |
"Preparser failed on:\n" |
"\t%s\n" |
@@ -1638,7 +1644,8 @@ void TestParserSyncWithFlags(i::Handle<i::String> source, |
"However, parser and preparser succeeded", |
source->ToCString().get()); |
CHECK(false); |
- } else if (preparser_materialized_literals != parser_materialized_literals) { |
+ } else if (test_preparser && |
+ preparser_materialized_literals != parser_materialized_literals) { |
v8::base::OS::Print( |
"Preparser materialized literals (%d) differ from Parser materialized " |
"literals (%d) on:\n" |
@@ -1651,14 +1658,14 @@ void TestParserSyncWithFlags(i::Handle<i::String> source, |
} |
-void TestParserSync(const char* source, |
- const ParserFlag* varying_flags, |
+void TestParserSync(const char* source, const ParserFlag* varying_flags, |
size_t varying_flags_length, |
ParserSyncTestResult result = kSuccessOrError, |
const ParserFlag* always_true_flags = NULL, |
size_t always_true_flags_length = 0, |
const ParserFlag* always_false_flags = NULL, |
- size_t always_false_flags_length = 0) { |
+ size_t always_false_flags_length = 0, |
+ bool is_module = false) { |
i::Handle<i::String> str = |
CcTest::i_isolate()->factory()->NewStringFromAsciiChecked(source); |
for (int bits = 0; bits < (1 << varying_flags_length); bits++) { |
@@ -1675,7 +1682,7 @@ void TestParserSync(const char* source, |
++flag_index) { |
flags.Remove(always_false_flags[flag_index]); |
} |
- TestParserSyncWithFlags(str, flags, result); |
+ TestParserSyncWithFlags(str, flags, result, is_module); |
} |
} |
@@ -1819,12 +1826,11 @@ TEST(StrictOctal) { |
void RunParserSyncTest(const char* context_data[][2], |
const char* statement_data[], |
ParserSyncTestResult result, |
- const ParserFlag* flags = NULL, |
- int flags_len = 0, |
+ const ParserFlag* flags = NULL, int flags_len = 0, |
const ParserFlag* always_true_flags = NULL, |
int always_true_len = 0, |
const ParserFlag* always_false_flags = NULL, |
- int always_false_len = 0) { |
+ int always_false_len = 0, bool is_module = false) { |
v8::HandleScope handles(CcTest::isolate()); |
v8::Local<v8::Context> context = v8::Context::New(CcTest::isolate()); |
v8::Context::Scope context_scope(context); |
@@ -1877,20 +1883,32 @@ void RunParserSyncTest(const char* context_data[][2], |
statement_data[j], |
context_data[i][1]); |
CHECK(length == kProgramSize); |
- TestParserSync(program.start(), |
- flags, |
- flags_len, |
- result, |
- always_true_flags, |
- always_true_len, |
- always_false_flags, |
- always_false_len); |
+ TestParserSync(program.start(), flags, flags_len, result, |
+ always_true_flags, always_true_len, always_false_flags, |
+ always_false_len, is_module); |
} |
} |
delete[] generated_flags; |
} |
+void RunModuleParserSyncTest(const char* context_data[][2], |
+ const char* statement_data[], |
+ ParserSyncTestResult result, |
+ const ParserFlag* flags = NULL, int flags_len = 0, |
+ const ParserFlag* always_true_flags = NULL, |
+ int always_true_len = 0, |
+ const ParserFlag* always_false_flags = NULL, |
+ int always_false_len = 0) { |
+ bool flag = i::FLAG_harmony_modules; |
+ i::FLAG_harmony_modules = true; |
+ RunParserSyncTest(context_data, statement_data, result, flags, flags_len, |
+ always_true_flags, always_true_len, always_false_flags, |
+ always_false_len, true); |
+ i::FLAG_harmony_modules = flag; |
+} |
+ |
+ |
TEST(ErrorsEvalAndArguments) { |
// Tests that both preparsing and parsing produce the right kind of errors for |
// using "eval" and "arguments" as identifiers. Without the strict mode, it's |
@@ -7305,3 +7323,151 @@ TEST(LetSloppyOnly) { |
RunParserSyncTest(context_data, fail_data, kError, NULL, 0, fail_flags, |
arraysize(fail_flags)); |
} |
+ |
+ |
+TEST(EscapedKeywords) { |
+ // clang-format off |
+ const char* sloppy_context_data[][2] = { |
+ {"", ""}, |
+ {NULL, NULL} |
+ }; |
+ |
+ const char* strict_context_data[][2] = { |
+ {"'use strict';", ""}, |
+ {NULL, NULL} |
+ }; |
+ |
+ const char* fail_data[] = { |
+ "for (var i = 0; i < 100; ++i) { br\\u0065ak; }", |
+ "cl\\u0061ss Foo {}", |
+ "var x = cl\\u0061ss {}", |
+ "\\u0063onst foo = 1;", |
+ "while (i < 10) { if (i++ & 1) c\\u006fntinue; this.x++; }", |
+ "d\\u0065bugger;", |
+ "d\\u0065lete this.a;", |
+ "\\u0063o { } while(0)", |
+ "if (d\\u006f { true }) {}", |
+ "if (false) { this.a = 1; } \\u0065lse { this.b = 1; }", |
+ "e\\u0078port var foo;", |
+ "try { } catch (e) {} f\\u0069nally { }", |
+ "f\\u006fr (var i = 0; i < 10; ++i);", |
+ "f\\u0075nction fn() {}", |
+ "var f = f\\u0075nction() {}", |
+ "\\u0069f (true) { }", |
+ "\\u0069mport blah from './foo.js';", |
+ "n\\u0065w function f() {}", |
+ "(function() { r\\u0065turn; })()", |
+ "class C extends function() {} { constructor() { sup\\u0065r() } }", |
+ "class C extends function() {} { constructor() { sup\\u0065r.a = 1 } }", |
+ "sw\\u0069tch (this.a) {}", |
+ "var x = th\\u0069s;", |
+ "th\\u0069s.a = 1;", |
+ "thr\\u006fw 'boo';", |
+ "t\\u0072y { true } catch (e) {}", |
+ "var x = typ\\u0065of 'blah'", |
+ "v\\u0061r a = true", |
+ "var v\\u0061r = true", |
+ "(function() { return v\\u006fid 0; })()", |
+ "wh\\u0069le (true) { }", |
+ "w\\u0069th (this.scope) { }", |
+ "(function*() { y\\u0069eld 1; })()", |
+ |
+ "var \\u0065num = 1;", |
+ "var { \\u0065num } = {}", |
+ "(\\u0065num = 1);", |
+ |
+ // Null / Boolean literals |
+ "(x === n\\u0075ll);", |
+ "var x = n\\u0075ll;", |
+ "var n\\u0075ll = 1;", |
+ "var { n\\u0075ll } = { 1 };", |
+ "n\\u0075ll = 1;", |
+ "(x === tr\\u0075e);", |
+ "var x = tr\\u0075e;", |
+ "var tr\\u0075e = 1;", |
+ "var { tr\\u0075e } = {};", |
+ "tr\\u0075e = 1;", |
+ "(x === f\\u0061lse);", |
+ "var x = f\\u0061lse;", |
+ "var f\\u0061lse = 1;", |
+ "var { f\\u0061lse } = {};", |
+ "f\\u0061lse = 1;", |
+ |
+ // TODO(caitp): consistent error messages for labeled statements and |
+ // expressions |
+ "switch (this.a) { c\\u0061se 6: break; }", |
+ "try { } c\\u0061tch (e) {}", |
+ "switch (this.a) { d\\u0065fault: break; }", |
+ "class C \\u0065xtends function B() {} {}", |
+ "for (var a i\\u006e this) {}", |
+ "if ('foo' \\u0069n this) {}", |
+ "if (this \\u0069nstanceof Array) {}", |
+ "(n\\u0065w function f() {})", |
+ "(typ\\u0065of 123)", |
+ "(v\\u006fid 0)", |
+ "do { ; } wh\\u0069le (true) { }", |
+ "(function*() { return (n++, y\\u0069eld 1); })()", |
+ "class C { st\\u0061tic bar() {} }", |
+ |
+ "(y\\u0069eld);", |
+ "var y\\u0069eld = 1;", |
+ "var { y\\u0069eld } = {};", |
+ NULL |
+ }; |
+ // clang-format on |
+ |
+ static const ParserFlag always_flags[] = {kAllowHarmonySloppy, |
+ kAllowHarmonyDestructuring}; |
+ RunParserSyncTest(sloppy_context_data, fail_data, kError, NULL, 0, |
+ always_flags, arraysize(always_flags)); |
+ RunParserSyncTest(strict_context_data, fail_data, kError, NULL, 0, |
+ always_flags, arraysize(always_flags)); |
+ RunModuleParserSyncTest(sloppy_context_data, fail_data, kError, NULL, 0, |
+ always_flags, arraysize(always_flags)); |
+ |
+ // clang-format off |
+ const char* let_data[] = { |
+ "var l\\u0065t = 1;", |
+ "l\\u0065t = 1;", |
+ "(l\\u0065t === 1);", |
+ NULL |
+ }; |
+ // clang-format on |
+ |
+ RunParserSyncTest(sloppy_context_data, let_data, kError, NULL, 0, |
+ always_flags, arraysize(always_flags)); |
+ RunParserSyncTest(strict_context_data, let_data, kError, NULL, 0, |
+ always_flags, arraysize(always_flags)); |
+ |
+ static const ParserFlag sloppy_let_flags[] = { |
+ kAllowHarmonySloppy, kAllowHarmonySloppyLet, kAllowHarmonyDestructuring}; |
+ RunParserSyncTest(sloppy_context_data, let_data, kError, NULL, 0, |
+ sloppy_let_flags, arraysize(sloppy_let_flags)); |
+ |
+ // Non-errors in sloppy mode |
+ const char* valid_data[] = {"(\\u0069mplements = 1);", |
+ "var impl\\u0065ments = 1;", |
+ "var { impl\\u0065ments } = {};", |
+ "(\\u0069nterface = 1);", |
+ "var int\\u0065rface = 1;", |
+ "var { int\\u0065rface } = {};", |
+ "(p\\u0061ckage = 1);", |
+ "var packa\\u0067e = 1;", |
+ "var { packa\\u0067e } = {};", |
+ "(p\\u0072ivate = 1);", |
+ "var p\\u0072ivate;", |
+ "var { p\\u0072ivate } = {};", |
+ "(prot\\u0065cted);", |
+ "var prot\\u0065cted = 1;", |
+ "var { prot\\u0065cted } = {};", |
+ "(publ\\u0069c);", |
+ "var publ\\u0069c = 1;", |
+ "var { publ\\u0069c } = {};", |
+ NULL}; |
+ RunParserSyncTest(sloppy_context_data, valid_data, kSuccess, NULL, 0, |
+ always_flags, arraysize(always_flags)); |
+ RunParserSyncTest(strict_context_data, valid_data, kError, NULL, 0, |
+ always_flags, arraysize(always_flags)); |
+ RunModuleParserSyncTest(strict_context_data, valid_data, kError, NULL, 0, |
+ always_flags, arraysize(always_flags)); |
+} |