summaryrefslogtreecommitdiff
path: root/deps/v8/test/cctest/test-parsing.cc
diff options
context:
space:
mode:
Diffstat (limited to 'deps/v8/test/cctest/test-parsing.cc')
-rw-r--r--deps/v8/test/cctest/test-parsing.cc295
1 files changed, 243 insertions, 52 deletions
diff --git a/deps/v8/test/cctest/test-parsing.cc b/deps/v8/test/cctest/test-parsing.cc
index 196c154bae..c2ee2b2452 100644
--- a/deps/v8/test/cctest/test-parsing.cc
+++ b/deps/v8/test/cctest/test-parsing.cc
@@ -78,7 +78,7 @@ TEST(ScanKeywords) {
{
auto stream = i::ScannerStream::ForTesting(keyword, length);
i::Scanner scanner(&unicode_cache);
- scanner.Initialize(stream.get());
+ scanner.Initialize(stream.get(), false);
CHECK_EQ(key_token.token, scanner.Next());
CHECK_EQ(i::Token::EOS, scanner.Next());
}
@@ -86,7 +86,7 @@ TEST(ScanKeywords) {
{
auto stream = i::ScannerStream::ForTesting(keyword, length - 1);
i::Scanner scanner(&unicode_cache);
- scanner.Initialize(stream.get());
+ scanner.Initialize(stream.get(), false);
CHECK_EQ(i::Token::IDENTIFIER, scanner.Next());
CHECK_EQ(i::Token::EOS, scanner.Next());
}
@@ -97,7 +97,7 @@ TEST(ScanKeywords) {
buffer[length] = chars_to_append[j];
auto stream = i::ScannerStream::ForTesting(buffer, length + 1);
i::Scanner scanner(&unicode_cache);
- scanner.Initialize(stream.get());
+ scanner.Initialize(stream.get(), false);
CHECK_EQ(i::Token::IDENTIFIER, scanner.Next());
CHECK_EQ(i::Token::EOS, scanner.Next());
}
@@ -107,7 +107,7 @@ TEST(ScanKeywords) {
buffer[length - 1] = '_';
auto stream = i::ScannerStream::ForTesting(buffer, length);
i::Scanner scanner(&unicode_cache);
- scanner.Initialize(stream.get());
+ scanner.Initialize(stream.get(), false);
CHECK_EQ(i::Token::IDENTIFIER, scanner.Next());
CHECK_EQ(i::Token::EOS, scanner.Next());
}
@@ -173,7 +173,7 @@ TEST(ScanHTMLEndComments) {
const char* source = tests[i];
auto stream = i::ScannerStream::ForTesting(source);
i::Scanner scanner(CcTest::i_isolate()->unicode_cache());
- scanner.Initialize(stream.get());
+ scanner.Initialize(stream.get(), false);
i::Zone zone(CcTest::i_isolate()->allocator(), ZONE_NAME);
i::AstValueFactory ast_value_factory(
&zone, CcTest::i_isolate()->ast_string_constants(),
@@ -192,7 +192,7 @@ TEST(ScanHTMLEndComments) {
const char* source = fail_tests[i];
auto stream = i::ScannerStream::ForTesting(source);
i::Scanner scanner(CcTest::i_isolate()->unicode_cache());
- scanner.Initialize(stream.get());
+ scanner.Initialize(stream.get(), false);
i::Zone zone(CcTest::i_isolate()->allocator(), ZONE_NAME);
i::AstValueFactory ast_value_factory(
&zone, CcTest::i_isolate()->ast_string_constants(),
@@ -209,6 +209,28 @@ TEST(ScanHTMLEndComments) {
}
}
+TEST(ScanHtmlComments) {
+ const char* src = "a <!-- b --> c";
+ i::UnicodeCache unicode_cache;
+
+ // Disallow HTML comments.
+ {
+ auto stream = i::ScannerStream::ForTesting(src);
+ i::Scanner scanner(&unicode_cache);
+ scanner.Initialize(stream.get(), true);
+ CHECK_EQ(i::Token::IDENTIFIER, scanner.Next());
+ CHECK_EQ(i::Token::ILLEGAL, scanner.Next());
+ }
+
+ // Skip HTML comments:
+ {
+ auto stream = i::ScannerStream::ForTesting(src);
+ i::Scanner scanner(&unicode_cache);
+ scanner.Initialize(stream.get(), false);
+ CHECK_EQ(i::Token::IDENTIFIER, scanner.Next());
+ CHECK_EQ(i::Token::EOS, scanner.Next());
+ }
+}
class ScriptResource : public v8::String::ExternalOneByteStringResource {
public:
@@ -365,7 +387,7 @@ TEST(StandAlonePreParser) {
for (int i = 0; programs[i]; i++) {
auto stream = i::ScannerStream::ForTesting(programs[i]);
i::Scanner scanner(CcTest::i_isolate()->unicode_cache());
- scanner.Initialize(stream.get());
+ scanner.Initialize(stream.get(), false);
i::Zone zone(CcTest::i_isolate()->allocator(), ZONE_NAME);
i::AstValueFactory ast_value_factory(
@@ -401,7 +423,7 @@ TEST(StandAlonePreParserNoNatives) {
for (int i = 0; programs[i]; i++) {
auto stream = i::ScannerStream::ForTesting(programs[i]);
i::Scanner scanner(isolate->unicode_cache());
- scanner.Initialize(stream.get());
+ scanner.Initialize(stream.get(), false);
// Preparser defaults to disallowing natives syntax.
i::Zone zone(CcTest::i_isolate()->allocator(), ZONE_NAME);
@@ -471,7 +493,7 @@ TEST(RegressChromium62639) {
auto stream = i::ScannerStream::ForTesting(program);
i::Scanner scanner(CcTest::i_isolate()->unicode_cache());
- scanner.Initialize(stream.get());
+ scanner.Initialize(stream.get(), false);
i::Zone zone(CcTest::i_isolate()->allocator(), ZONE_NAME);
i::AstValueFactory ast_value_factory(
&zone, CcTest::i_isolate()->ast_string_constants(),
@@ -548,7 +570,7 @@ TEST(PreParseOverflow) {
auto stream = i::ScannerStream::ForTesting(program.get(), kProgramSize);
i::Scanner scanner(isolate->unicode_cache());
- scanner.Initialize(stream.get());
+ scanner.Initialize(stream.get(), false);
i::Zone zone(CcTest::i_isolate()->allocator(), ZONE_NAME);
i::AstValueFactory ast_value_factory(
@@ -568,7 +590,7 @@ void TestStreamScanner(i::Utf16CharacterStream* stream,
int skip_pos = 0, // Zero means not skipping.
int skip_to = 0) {
i::Scanner scanner(CcTest::i_isolate()->unicode_cache());
- scanner.Initialize(stream);
+ scanner.Initialize(stream, false);
int i = 0;
do {
@@ -646,7 +668,7 @@ void TestScanRegExp(const char* re_source, const char* expected) {
auto stream = i::ScannerStream::ForTesting(re_source);
i::HandleScope scope(CcTest::i_isolate());
i::Scanner scanner(CcTest::i_isolate()->unicode_cache());
- scanner.Initialize(stream.get());
+ scanner.Initialize(stream.get(), false);
i::Token::Value start = scanner.peek();
CHECK(start == i::Token::DIV || start == i::Token::ASSIGN_DIV);
@@ -845,8 +867,7 @@ TEST(ScopeUsesArgumentsSuperThis) {
}
}
-
-static void CheckParsesToNumber(const char* source, bool with_dot) {
+static void CheckParsesToNumber(const char* source) {
v8::V8::Initialize();
HandleAndZoneScope handles;
@@ -877,40 +898,27 @@ static void CheckParsesToNumber(const char* source, bool with_dot) {
CHECK(fun->body()->at(0)->IsReturnStatement());
i::ReturnStatement* ret = fun->body()->at(0)->AsReturnStatement();
i::Literal* lit = ret->expression()->AsLiteral();
- if (lit != NULL) {
- const i::AstValue* val = lit->raw_value();
- CHECK(with_dot == val->ContainsDot());
- } else if (with_dot) {
- i::BinaryOperation* bin = ret->expression()->AsBinaryOperation();
- CHECK(bin != NULL);
- CHECK_EQ(i::Token::MUL, bin->op());
- i::Literal* rlit = bin->right()->AsLiteral();
- const i::AstValue* val = rlit->raw_value();
- CHECK(with_dot == val->ContainsDot());
- CHECK_EQ(1.0, val->AsNumber());
- }
+ CHECK(lit->IsNumberLiteral());
}
TEST(ParseNumbers) {
- CheckParsesToNumber("1.", true);
- CheckParsesToNumber("1.34", true);
- CheckParsesToNumber("134", false);
- CheckParsesToNumber("134e44", false);
- CheckParsesToNumber("134.e44", true);
- CheckParsesToNumber("134.44e44", true);
- CheckParsesToNumber(".44", true);
-
- CheckParsesToNumber("-1.", true);
- CheckParsesToNumber("-1.0", true);
- CheckParsesToNumber("-1.34", true);
- CheckParsesToNumber("-134", false);
- CheckParsesToNumber("-134e44", false);
- CheckParsesToNumber("-134.e44", true);
- CheckParsesToNumber("-134.44e44", true);
- CheckParsesToNumber("-.44", true);
+ CheckParsesToNumber("1.");
+ CheckParsesToNumber("1.34");
+ CheckParsesToNumber("134");
+ CheckParsesToNumber("134e44");
+ CheckParsesToNumber("134.e44");
+ CheckParsesToNumber("134.44e44");
+ CheckParsesToNumber(".44");
- CheckParsesToNumber("+x", true);
+ CheckParsesToNumber("-1.");
+ CheckParsesToNumber("-1.0");
+ CheckParsesToNumber("-1.34");
+ CheckParsesToNumber("-134");
+ CheckParsesToNumber("-134e44");
+ CheckParsesToNumber("-134.e44");
+ CheckParsesToNumber("-134.44e44");
+ CheckParsesToNumber("-.44");
}
@@ -1334,7 +1342,7 @@ void TestParserSyncWithFlags(i::Handle<i::String> source,
&pending_error_handler,
isolate->counters()->runtime_call_stats());
SetParserFlags(&preparser, flags);
- scanner.Initialize(stream.get());
+ scanner.Initialize(stream.get(), is_module);
i::PreParser::PreParseResult result = preparser.PreParseProgram(is_module);
CHECK_EQ(i::PreParser::kPreParseSuccess, result);
}
@@ -3521,14 +3529,7 @@ static void TestMaybeAssigned(Input input, const char* variable, bool module,
i::Variable* var;
{
// Find the variable.
- for (auto it = input.location.begin(); it != input.location.end(); ++it) {
- unsigned n = *it;
- scope = scope->inner_scope();
- while (n-- > 0) {
- scope = scope->sibling();
- }
- }
- CHECK_NOT_NULL(scope);
+ scope = i::ScopeTestHelper::FindScope(scope, input.location);
const i::AstRawString* var_name =
info->ast_value_factory()->GetOneByteString(variable);
var = scope->Lookup(var_name);
@@ -4240,6 +4241,7 @@ TEST(ErrorsArrowFunctions) {
"(c, a.b) => {}",
"(a['b'], c) => {}",
"(c, a['b']) => {}",
+ "(...a = b) => b",
// crbug.com/582626
"(...rest - a) => b",
@@ -8967,6 +8969,10 @@ TEST(AsyncAwaitErrors) {
// v8:5148 assert that errors are still thrown for calls that may have been
// async functions
"async({ foo33 = 1 })",
+
+ "async(...a = b) => b",
+ "async(...a,) => b",
+ "async(...a, b) => b",
NULL
};
@@ -10161,3 +10167,188 @@ TEST(AsyncGeneratorErrors) {
RunParserSyncTest(context_data, statement_data, kError, NULL, 0, always_flags,
arraysize(always_flags));
}
+
+TEST(LexicalLoopVariable) {
+ i::Isolate* isolate = CcTest::i_isolate();
+ i::HandleScope scope(isolate);
+ LocalContext env;
+ typedef std::function<void(const i::ParseInfo& info, i::DeclarationScope*)>
+ TestCB;
+ auto TestProgram = [isolate](const char* program, TestCB test) {
+ i::Factory* const factory = isolate->factory();
+ i::Handle<i::String> source =
+ factory->NewStringFromUtf8(i::CStrVector(program)).ToHandleChecked();
+ i::Handle<i::Script> script = factory->NewScript(source);
+ i::ParseInfo info(script);
+
+ info.set_allow_lazy_parsing(false);
+ CHECK(i::parsing::ParseProgram(&info, isolate));
+ CHECK(i::Rewriter::Rewrite(&info, isolate));
+ i::DeclarationScope::Analyze(&info, isolate, i::AnalyzeMode::kRegular);
+ CHECK(info.literal() != NULL);
+
+ i::DeclarationScope* script_scope = info.literal()->scope();
+ CHECK(script_scope->is_script_scope());
+
+ test(info, script_scope);
+ };
+
+ // Check `let` loop variables is a stack local when not captured by an eval
+ // or closure within the area of the loop body.
+ const char* local_bindings[] = {
+ "function loop() {"
+ " for (let loop_var = 0; loop_var < 10; ++loop_var) {"
+ " }"
+ " eval('0');"
+ "}",
+
+ "function loop() {"
+ " for (let loop_var = 0; loop_var < 10; ++loop_var) {"
+ " }"
+ " function foo() {}"
+ " foo();"
+ "}",
+ };
+ for (const char* source : local_bindings) {
+ TestProgram(source, [=](const i::ParseInfo& info, i::DeclarationScope* s) {
+ i::Scope* fn = s->inner_scope();
+ CHECK(fn->is_function_scope());
+
+ i::Scope* loop_block = fn->inner_scope();
+ if (loop_block->is_function_scope()) loop_block = loop_block->sibling();
+ CHECK(loop_block->is_block_scope());
+
+ const i::AstRawString* var_name =
+ info.ast_value_factory()->GetOneByteString("loop_var");
+ i::Variable* loop_var = loop_block->LookupLocal(var_name);
+ CHECK_NOT_NULL(loop_var);
+ CHECK(loop_var->IsStackLocal());
+ CHECK_EQ(loop_block->ContextLocalCount(), 0);
+ CHECK_EQ(loop_block->inner_scope()->ContextLocalCount(), 0);
+ });
+ }
+
+ // Check `let` loop variable is not a stack local, and is duplicated in the
+ // loop body to ensure capturing can work correctly.
+ // In this version of the test, the inner loop block's duplicate `loop_var`
+ // binding is not captured, and is a local.
+ const char* context_bindings1[] = {
+ "function loop() {"
+ " for (let loop_var = eval('0'); loop_var < 10; ++loop_var) {"
+ " }"
+ "}",
+
+ "function loop() {"
+ " for (let loop_var = (() => (loop_var, 0))(); loop_var < 10;"
+ " ++loop_var) {"
+ " }"
+ "}"};
+ for (const char* source : context_bindings1) {
+ TestProgram(source, [=](const i::ParseInfo& info, i::DeclarationScope* s) {
+ i::Scope* fn = s->inner_scope();
+ CHECK(fn->is_function_scope());
+
+ i::Scope* loop_block = fn->inner_scope();
+ CHECK(loop_block->is_block_scope());
+
+ const i::AstRawString* var_name =
+ info.ast_value_factory()->GetOneByteString("loop_var");
+ i::Variable* loop_var = loop_block->LookupLocal(var_name);
+ CHECK_NOT_NULL(loop_var);
+ CHECK(loop_var->IsContextSlot());
+ CHECK_EQ(loop_block->ContextLocalCount(), 1);
+
+ i::Variable* loop_var2 = loop_block->inner_scope()->LookupLocal(var_name);
+ CHECK_NE(loop_var, loop_var2);
+ CHECK(loop_var2->IsStackLocal());
+ CHECK_EQ(loop_block->inner_scope()->ContextLocalCount(), 0);
+ });
+ }
+
+ // Check `let` loop variable is not a stack local, and is duplicated in the
+ // loop body to ensure capturing can work correctly.
+ // In this version of the test, the inner loop block's duplicate `loop_var`
+ // binding is captured, and must be context allocated.
+ const char* context_bindings2[] = {
+ "function loop() {"
+ " for (let loop_var = 0; loop_var < 10; ++loop_var) {"
+ " eval('0');"
+ " }"
+ "}",
+
+ "function loop() {"
+ " for (let loop_var = 0; loop_var < eval('10'); ++loop_var) {"
+ " }"
+ "}",
+
+ "function loop() {"
+ " for (let loop_var = 0; loop_var < 10; eval('++loop_var')) {"
+ " }"
+ "}",
+ };
+
+ for (const char* source : context_bindings2) {
+ TestProgram(source, [=](const i::ParseInfo& info, i::DeclarationScope* s) {
+ i::Scope* fn = s->inner_scope();
+ CHECK(fn->is_function_scope());
+
+ i::Scope* loop_block = fn->inner_scope();
+ CHECK(loop_block->is_block_scope());
+
+ const i::AstRawString* var_name =
+ info.ast_value_factory()->GetOneByteString("loop_var");
+ i::Variable* loop_var = loop_block->LookupLocal(var_name);
+ CHECK_NOT_NULL(loop_var);
+ CHECK(loop_var->IsContextSlot());
+ CHECK_EQ(loop_block->ContextLocalCount(), 1);
+
+ i::Variable* loop_var2 = loop_block->inner_scope()->LookupLocal(var_name);
+ CHECK_NE(loop_var, loop_var2);
+ CHECK(loop_var2->IsContextSlot());
+ CHECK_EQ(loop_block->inner_scope()->ContextLocalCount(), 1);
+ });
+ }
+
+ // Similar to the above, but the first block scope's variables are not
+ // captured due to the closure occurring in a nested scope.
+ const char* context_bindings3[] = {
+ "function loop() {"
+ " for (let loop_var = 0; loop_var < 10; ++loop_var) {"
+ " (() => loop_var)();"
+ " }"
+ "}",
+
+ "function loop() {"
+ " for (let loop_var = 0; loop_var < (() => (loop_var, 10))();"
+ " ++loop_var) {"
+ " }"
+ "}",
+
+ "function loop() {"
+ " for (let loop_var = 0; loop_var < 10; (() => ++loop_var)()) {"
+ " }"
+ "}",
+ };
+
+ for (const char* source : context_bindings3) {
+ TestProgram(source, [=](const i::ParseInfo& info, i::DeclarationScope* s) {
+ i::Scope* fn = s->inner_scope();
+ CHECK(fn->is_function_scope());
+
+ i::Scope* loop_block = fn->inner_scope();
+ CHECK(loop_block->is_block_scope());
+
+ const i::AstRawString* var_name =
+ info.ast_value_factory()->GetOneByteString("loop_var");
+ i::Variable* loop_var = loop_block->LookupLocal(var_name);
+ CHECK_NOT_NULL(loop_var);
+ CHECK(loop_var->IsStackLocal());
+ CHECK_EQ(loop_block->ContextLocalCount(), 0);
+
+ i::Variable* loop_var2 = loop_block->inner_scope()->LookupLocal(var_name);
+ CHECK_NE(loop_var, loop_var2);
+ CHECK(loop_var2->IsContextSlot());
+ CHECK_EQ(loop_block->inner_scope()->ContextLocalCount(), 1);
+ });
+ }
+}