[modules] Treat top-level functions as lexical

[15.2.1.11 Static Semantics:
LexicallyDeclaredNames](https://tc39.github.io/ecma262/#sec-module-semantics-static-semantics-lexicallydeclarednames)
(in contrast with its definition for StatementListItem) makes no
explicit provision for HoistableDeclarations. This means that function
declarations are treated as lexically scoped in module code, as
described in section 15.2.1.11's informative note:

> At the top level of a function, or script, function declarations are
> treated like var declarations rather than like lexical declarations.

BUG=v8:4884
LOG=N
R=adamk@chromium.org

Review URL: https://codereview.chromium.org/1851673007

Cr-Commit-Position: refs/heads/master@{#35633}
This commit is contained in:
mike 2016-04-19 10:51:53 -07:00 committed by Commit bot
parent 59546149c6
commit 43fa3e65c9
2 changed files with 40 additions and 1 deletions

View File

@ -2085,7 +2085,9 @@ Statement* Parser::ParseFunctionDeclaration(
// initial value upon entering the corresponding scope.
// In ES6, a function behaves as a lexical binding, except in
// a script scope, or the initial scope of eval or another function.
VariableMode mode = !scope_->is_declaration_scope() ? LET : VAR;
VariableMode mode =
(!scope_->is_declaration_scope() || scope_->is_module_scope()) ? LET
: VAR;
VariableProxy* proxy = NewUnresolved(name, mode);
Declaration* declaration =
factory()->NewFunctionDeclaration(proxy, mode, fun, scope_, pos);

View File

@ -5628,6 +5628,43 @@ TEST(ImportExportParsingErrors) {
}
}
TEST(ModuleTopLevelFunctionDecl) {
// clang-format off
const char* kErrorSources[] = {
"function f() {} function f() {}",
"var f; function f() {}",
"function f() {} var f;",
"function* f() {} function* f() {}",
"var f; function* f() {}",
"function* f() {} var f;",
"function f() {} function* f() {}",
"function* f() {} function f() {}",
};
// clang-format on
i::Isolate* isolate = CcTest::i_isolate();
i::Factory* factory = isolate->factory();
v8::HandleScope handles(CcTest::isolate());
v8::Local<v8::Context> context = v8::Context::New(CcTest::isolate());
v8::Context::Scope context_scope(context);
isolate->stack_guard()->SetStackLimit(i::GetCurrentStackPosition() -
128 * 1024);
for (unsigned i = 0; i < arraysize(kErrorSources); ++i) {
i::Handle<i::String> source =
factory->NewStringFromAsciiChecked(kErrorSources[i]);
i::Handle<i::Script> script = factory->NewScript(source);
i::Zone zone(CcTest::i_isolate()->allocator());
i::ParseInfo info(&zone, script);
i::Parser parser(&info);
info.set_module();
CHECK(!parser.Parse(&info));
}
}
TEST(ModuleParsingInternals) {
i::Isolate* isolate = CcTest::i_isolate();