Commit 43fa3e65 authored by mike's avatar mike Committed by Commit bot

[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}
parent 59546149
......@@ -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);
......
......@@ -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();
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment