[top-level-await] Add support for parsing top level await

Adds support for parsing top level await to V8, as well as
many tests.

This is the final cl in the series to add support for top level
await to v8.

Spec is here:
https://tc39.es/proposal-top-level-await/#sec-execute-async-module

Bug: v8:9344
Change-Id: Ie8f17ad8c7c60d1f6996d134ae154416cc1f31e3
Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/1703878
Reviewed-by: Georg Neis <neis@chromium.org>
Reviewed-by: Adam Klein <adamk@chromium.org>
Commit-Queue: Joshua Litt <joshualitt@chromium.org>
Cr-Commit-Position: refs/heads/master@{#63946}
diff --git a/src/ast/scopes.h b/src/ast/scopes.h
index d28a2f2..c080e98 100644
--- a/src/ast/scopes.h
+++ b/src/ast/scopes.h
@@ -865,6 +865,11 @@
     return IsClassMembersInitializerFunction(function_kind());
   }
 
+  void set_is_async_module() {
+    DCHECK(IsModule(function_kind_));
+    function_kind_ = kAsyncModule;
+  }
+
   void DeclareThis(AstValueFactory* ast_value_factory);
   void DeclareArguments(AstValueFactory* ast_value_factory);
   void DeclareDefaultFunctionVariables(AstValueFactory* ast_value_factory);
@@ -1143,7 +1148,7 @@
   bool needs_private_name_context_chain_recalc_ : 1;
 
   // If the scope is a function scope, this is the function kind.
-  const FunctionKind function_kind_;
+  FunctionKind function_kind_;
 
   int num_parameters_ = 0;
 
diff --git a/src/builtins/base.tq b/src/builtins/base.tq
index 628705f..cf6a083 100644
--- a/src/builtins/base.tq
+++ b/src/builtins/base.tq
@@ -727,7 +727,7 @@
   bound_target_function: Callable;
   // The value that is always passed as the this value when calling the wrapped
   // function.
-  bound_this: JSAny;
+  bound_this: JSAny | SourceTextModule;
   // A list of values whose elements are used as the first arguments to any call
   // to the wrapped function.
   bound_arguments: FixedArray;
diff --git a/src/diagnostics/objects-debug.cc b/src/diagnostics/objects-debug.cc
index 0083ec3..4721ff5 100644
--- a/src/diagnostics/objects-debug.cc
+++ b/src/diagnostics/objects-debug.cc
@@ -26,6 +26,7 @@
 #include "src/objects/field-type.h"
 #include "src/objects/foreign-inl.h"
 #include "src/objects/free-space-inl.h"
+#include "src/objects/function-kind.h"
 #include "src/objects/hash-table-inl.h"
 #include "src/objects/js-array-inl.h"
 #include "src/objects/layout-descriptor.h"
@@ -1050,7 +1051,7 @@
   if (scope_info().length() > 0) {
     ScopeInfo info = scope_info();
     CHECK(kind() == info.function_kind());
-    CHECK_EQ(kind() == kModule, info.scope_type() == MODULE_SCOPE);
+    CHECK_EQ(internal::IsModule(kind()), info.scope_type() == MODULE_SCOPE);
   }
 
   if (IsApiFunction()) {
diff --git a/src/heap/factory.cc b/src/heap/factory.cc
index f395e94..5fa38da 100644
--- a/src/heap/factory.cc
+++ b/src/heap/factory.cc
@@ -3058,7 +3058,7 @@
   module->set_dfs_ancestor_index(-1);
   module->set_top_level_capability(roots.undefined_value());
   module->set_flags(0);
-  module->set_async(false);
+  module->set_async(IsAsyncModule(code->kind()));
   module->set_async_evaluating(false);
   module->set_async_parent_modules(*async_parent_modules);
   module->set_pending_async_dependencies(0);
diff --git a/src/interpreter/bytecode-generator.cc b/src/interpreter/bytecode-generator.cc
index da1cb79..498c41b 100644
--- a/src/interpreter/bytecode-generator.cc
+++ b/src/interpreter/bytecode-generator.cc
@@ -3084,7 +3084,8 @@
         .StoreAccumulatorInRegister(args[2])  // done
         .CallRuntime(Runtime::kInlineAsyncGeneratorResolve, args);
   } else {
-    DCHECK(IsAsyncFunction(info()->literal()->kind()));
+    DCHECK(IsAsyncFunction(info()->literal()->kind()) ||
+           IsAsyncModule(info()->literal()->kind()));
     RegisterList args = register_allocator()->NewRegisterList(3);
     builder()
         ->MoveRegister(generator_object(), args[0])  // generator
@@ -6094,8 +6095,9 @@
   RegisterAllocationScope register_scope(this);
   RegisterList args = register_allocator()->NewRegisterList(2);
   Runtime::FunctionId function_id =
-      (IsAsyncFunction(info()->literal()->kind()) &&
-       !IsAsyncGeneratorFunction(info()->literal()->kind()))
+      ((IsAsyncFunction(info()->literal()->kind()) &&
+        !IsAsyncGeneratorFunction(info()->literal()->kind())) ||
+       IsAsyncModule(info()->literal()->kind()))
           ? Runtime::kInlineAsyncFunctionEnter
           : Runtime::kInlineCreateJSGeneratorObject;
   builder()
diff --git a/src/objects/contexts-inl.h b/src/objects/contexts-inl.h
index 0c566dd..7c232e2 100644
--- a/src/objects/contexts-inl.h
+++ b/src/objects/contexts-inl.h
@@ -197,7 +197,7 @@
     base = IsAsyncFunction(kind) ? ASYNC_GENERATOR_FUNCTION_MAP_INDEX
                                  : GENERATOR_FUNCTION_MAP_INDEX;
 
-  } else if (IsAsyncFunction(kind)) {
+  } else if (IsAsyncFunction(kind) || IsAsyncModule(kind)) {
     CHECK_FOLLOWS4(ASYNC_FUNCTION_MAP_INDEX, ASYNC_FUNCTION_WITH_NAME_MAP_INDEX,
                    ASYNC_FUNCTION_WITH_HOME_OBJECT_MAP_INDEX,
                    ASYNC_FUNCTION_WITH_NAME_AND_HOME_OBJECT_MAP_INDEX);
diff --git a/src/objects/function-kind.h b/src/objects/function-kind.h
index 8e9c68e..9b0de76 100644
--- a/src/objects/function-kind.h
+++ b/src/objects/function-kind.h
@@ -14,6 +14,7 @@
   // BEGIN constructable functions
   kNormalFunction,
   kModule,
+  kAsyncModule,
   // BEGIN class constructors
   // BEGIN base constructors
   kBaseConstructor,
@@ -61,7 +62,11 @@
 }
 
 inline bool IsModule(FunctionKind kind) {
-  return kind == FunctionKind::kModule;
+  return IsInRange(kind, FunctionKind::kModule, FunctionKind::kAsyncModule);
+}
+
+inline bool IsAsyncModule(FunctionKind kind) {
+  return kind == FunctionKind::kAsyncModule;
 }
 
 inline bool IsAsyncGeneratorFunction(FunctionKind kind) {
@@ -163,6 +168,8 @@
       return "AsyncFunction";
     case FunctionKind::kModule:
       return "Module";
+    case FunctionKind::kAsyncModule:
+      return "AsyncModule";
     case FunctionKind::kClassMembersInitializerFunction:
       return "ClassMembersInitializerFunction";
     case FunctionKind::kDefaultBaseConstructor:
diff --git a/src/parsing/parse-info.cc b/src/parsing/parse-info.cc
index 1588077..b0a455e 100644
--- a/src/parsing/parse-info.cc
+++ b/src/parsing/parse-info.cc
@@ -65,6 +65,7 @@
   set_allow_harmony_optional_chaining(FLAG_harmony_optional_chaining);
   set_allow_harmony_nullish(FLAG_harmony_nullish);
   set_allow_harmony_private_methods(FLAG_harmony_private_methods);
+  set_allow_harmony_top_level_await(FLAG_harmony_top_level_await);
 }
 
 ParseInfo::ParseInfo(Isolate* isolate)
diff --git a/src/parsing/parse-info.h b/src/parsing/parse-info.h
index 8afb124..dde331b 100644
--- a/src/parsing/parse-info.h
+++ b/src/parsing/parse-info.h
@@ -110,6 +110,8 @@
                 set_collect_source_positions)
   FLAG_ACCESSOR(kAllowHarmonyNullish, allow_harmony_nullish,
                 set_allow_harmony_nullish)
+  FLAG_ACCESSOR(kAllowHarmonyTopLevelAwait, allow_harmony_top_level_await,
+                set_allow_harmony_top_level_await)
 
 #undef FLAG_ACCESSOR
 
@@ -319,6 +321,7 @@
     kIsOneshotIIFE = 1 << 27,
     kCollectSourcePositions = 1 << 28,
     kAllowHarmonyNullish = 1 << 29,
+    kAllowHarmonyTopLevelAwait = 1 << 30,
   };
 
   //------------- Inputs to parsing and scope analysis -----------------------
diff --git a/src/parsing/parser-base.h b/src/parsing/parser-base.h
index 3a9960a..bab4128 100644
--- a/src/parsing/parser-base.h
+++ b/src/parsing/parser-base.h
@@ -267,6 +267,7 @@
         allow_harmony_dynamic_import_(false),
         allow_harmony_import_meta_(false),
         allow_harmony_private_methods_(false),
+        allow_harmony_top_level_await_(false),
         allow_eval_cache_(true) {
     pointer_buffer_.reserve(32);
     variable_buffer_.reserve(32);
@@ -280,6 +281,7 @@
   ALLOW_ACCESSORS(harmony_dynamic_import)
   ALLOW_ACCESSORS(harmony_import_meta)
   ALLOW_ACCESSORS(harmony_private_methods)
+  ALLOW_ACCESSORS(harmony_top_level_await)
   ALLOW_ACCESSORS(eval_cache)
 
 #undef ALLOW_ACCESSORS
@@ -1473,6 +1475,7 @@
   bool allow_harmony_dynamic_import_;
   bool allow_harmony_import_meta_;
   bool allow_harmony_private_methods_;
+  bool allow_harmony_top_level_await_;
   bool allow_eval_cache_;
 };
 
@@ -3080,7 +3083,9 @@
 
   Token::Value op = peek();
   if (Token::IsUnaryOrCountOp(op)) return ParseUnaryOrPrefixExpression();
-  if (is_async_function() && op == Token::AWAIT) {
+  if ((is_async_function() || (allow_harmony_top_level_await() &&
+                               IsModule(function_state_->kind()))) &&
+      op == Token::AWAIT) {
     return ParseAwaitExpression();
   }
   return ParsePostfixExpression();
diff --git a/src/parsing/parser.cc b/src/parsing/parser.cc
index cc1bf8b..9709426 100644
--- a/src/parsing/parser.cc
+++ b/src/parsing/parser.cc
@@ -427,6 +427,7 @@
   set_allow_harmony_nullish(info->allow_harmony_nullish());
   set_allow_harmony_optional_chaining(info->allow_harmony_optional_chaining());
   set_allow_harmony_private_methods(info->allow_harmony_private_methods());
+  set_allow_harmony_top_level_await(info->allow_harmony_top_level_await());
   for (int feature = 0; feature < v8::Isolate::kUseCounterFeatureCount;
        ++feature) {
     use_counts_[feature] = 0;
@@ -576,8 +577,32 @@
           BuildInitialYield(kNoSourcePosition, kGeneratorFunction);
       body.Add(
           factory()->NewExpressionStatement(initial_yield, kNoSourcePosition));
-
-      ParseModuleItemList(&body);
+      if (allow_harmony_top_level_await()) {
+        // First parse statements into a buffer. Then, if there was a
+        // top level await, create an inner block and rewrite the body of the
+        // module as an async function. Otherwise merge the statements back
+        // into the main body.
+        BlockT block = impl()->NullBlock();
+        {
+          StatementListT statements(pointer_buffer());
+          ParseModuleItemList(&statements);
+          // Modules will always have an initial yield. If there are any
+          // additional suspends, i.e. awaits, then we treat the module as an
+          // AsyncModule.
+          if (function_state.suspend_count() > 1) {
+            scope->set_is_async_module();
+            block = factory()->NewBlock(true, statements);
+          } else {
+            statements.MergeInto(&body);
+          }
+        }
+        if (IsAsyncModule(scope->function_kind())) {
+          impl()->RewriteAsyncFunctionBody(
+              &body, block, factory()->NewUndefinedLiteral(kNoSourcePosition));
+        }
+      } else {
+        ParseModuleItemList(&body);
+      }
       if (!has_error() &&
           !module()->Validate(this->scope()->AsModuleScope(),
                               pending_error_handler(), zone())) {
diff --git a/test/cctest/interpreter/bytecode_expectations/AsyncModules.golden b/test/cctest/interpreter/bytecode_expectations/AsyncModules.golden
new file mode 100644
index 0000000..7cbe661
--- /dev/null
+++ b/test/cctest/interpreter/bytecode_expectations/AsyncModules.golden
@@ -0,0 +1,349 @@
+#
+# Autogenerated by generate-bytecode-expectations.
+#
+
+---
+wrap: no
+module: yes
+top level: yes
+top level await: yes
+
+---
+snippet: "
+  await 42;
+"
+frame size: 8
+parameter count: 2
+bytecode array length: 142
+bytecodes: [
+                B(SwitchOnGeneratorState), R(0), U8(0), U8(2),
+                B(LdaConstant), U8(2),
+                B(Star), R(3),
+                B(Mov), R(arg0), R(2),
+                B(CallRuntime), U16(Runtime::kPushModuleContext), R(2), U8(2),
+                B(PushContext), R(2),
+                B(Mov), R(closure), R(3),
+                B(Mov), R(this), R(4),
+                B(InvokeIntrinsic), U8(Runtime::k_AsyncFunctionEnter), R(3), U8(2),
+                B(Star), R(0),
+  /*    0 E> */ B(StackCheck),
+  /*    0 E> */ B(SuspendGenerator), R(0), R(0), U8(3), U8(0),
+                B(ResumeGenerator), R(0), R(0), U8(3),
+                B(Star), R(3),
+                B(InvokeIntrinsic), U8(Runtime::k_GeneratorGetResumeMode), R(0), U8(1),
+                B(SwitchOnSmiNoFeedback), U8(3), U8(2), I8(0),
+                B(Ldar), R(3),
+  /*    0 E> */ B(Throw),
+                B(Ldar), R(3),
+  /*   10 S> */ B(Return),
+                B(Mov), R(3), R(1),
+                B(Ldar), R(1),
+                B(Mov), R(context), R(3),
+  /*    0 S> */ B(LdaSmi), I8(42),
+                B(Star), R(5),
+                B(Mov), R(0), R(4),
+                B(InvokeIntrinsic), U8(Runtime::k_AsyncFunctionAwaitUncaught), R(4), U8(2),
+  /*    0 E> */ B(SuspendGenerator), R(0), R(0), U8(4), U8(1),
+                B(ResumeGenerator), R(0), R(0), U8(4),
+                B(Star), R(4),
+                B(InvokeIntrinsic), U8(Runtime::k_GeneratorGetResumeMode), R(0), U8(1),
+                B(Star), R(5),
+                B(LdaZero),
+                B(TestReferenceEqual), R(5),
+                B(JumpIfTrue), U8(5),
+                B(Ldar), R(4),
+                B(ReThrow),
+                B(LdaUndefined),
+                B(Star), R(5),
+                B(LdaTrue),
+                B(Star), R(6),
+                B(Mov), R(0), R(4),
+                B(InvokeIntrinsic), U8(Runtime::k_AsyncFunctionResolve), R(4), U8(3),
+  /*   10 S> */ B(Return),
+                B(Star), R(4),
+                B(CreateCatchContext), R(4), U8(5),
+                B(Star), R(3),
+                B(LdaTheHole),
+                B(SetPendingMessage),
+                B(Ldar), R(3),
+                B(PushContext), R(4),
+                B(LdaImmutableCurrentContextSlot), U8(4),
+                B(Star), R(6),
+                B(LdaTrue),
+                B(Star), R(7),
+                B(Mov), R(0), R(5),
+                B(InvokeIntrinsic), U8(Runtime::k_AsyncFunctionReject), R(5), U8(3),
+  /*   10 S> */ B(Return),
+]
+constant pool: [
+  Smi [36],
+  Smi [80],
+  SCOPE_INFO_TYPE,
+  Smi [10],
+  Smi [7],
+  SCOPE_INFO_TYPE,
+]
+handlers: [
+  [64, 114, 114],
+]
+
+---
+snippet: "
+  await import(\"foo\");
+"
+frame size: 8
+parameter count: 2
+bytecode array length: 152
+bytecodes: [
+                B(SwitchOnGeneratorState), R(0), U8(0), U8(2),
+                B(LdaConstant), U8(2),
+                B(Star), R(3),
+                B(Mov), R(arg0), R(2),
+                B(CallRuntime), U16(Runtime::kPushModuleContext), R(2), U8(2),
+                B(PushContext), R(2),
+                B(Mov), R(closure), R(3),
+                B(Mov), R(this), R(4),
+                B(InvokeIntrinsic), U8(Runtime::k_AsyncFunctionEnter), R(3), U8(2),
+                B(Star), R(0),
+  /*    0 E> */ B(StackCheck),
+  /*    0 E> */ B(SuspendGenerator), R(0), R(0), U8(3), U8(0),
+                B(ResumeGenerator), R(0), R(0), U8(3),
+                B(Star), R(3),
+                B(InvokeIntrinsic), U8(Runtime::k_GeneratorGetResumeMode), R(0), U8(1),
+                B(SwitchOnSmiNoFeedback), U8(3), U8(2), I8(0),
+                B(Ldar), R(3),
+  /*    0 E> */ B(Throw),
+                B(Ldar), R(3),
+  /*   21 S> */ B(Return),
+                B(Mov), R(3), R(1),
+                B(Ldar), R(1),
+                B(Mov), R(context), R(3),
+  /*    0 S> */ B(LdaConstant), U8(5),
+                B(Star), R(5),
+                B(Mov), R(closure), R(4),
+                B(CallRuntime), U16(Runtime::kDynamicImportCall), R(4), U8(2),
+                B(Star), R(5),
+                B(Mov), R(0), R(4),
+                B(InvokeIntrinsic), U8(Runtime::k_AsyncFunctionAwaitUncaught), R(4), U8(2),
+  /*    0 E> */ B(SuspendGenerator), R(0), R(0), U8(4), U8(1),
+                B(ResumeGenerator), R(0), R(0), U8(4),
+                B(Star), R(4),
+                B(InvokeIntrinsic), U8(Runtime::k_GeneratorGetResumeMode), R(0), U8(1),
+                B(Star), R(5),
+                B(LdaZero),
+                B(TestReferenceEqual), R(5),
+                B(JumpIfTrue), U8(5),
+                B(Ldar), R(4),
+                B(ReThrow),
+                B(LdaUndefined),
+                B(Star), R(5),
+                B(LdaTrue),
+                B(Star), R(6),
+                B(Mov), R(0), R(4),
+                B(InvokeIntrinsic), U8(Runtime::k_AsyncFunctionResolve), R(4), U8(3),
+  /*   21 S> */ B(Return),
+                B(Star), R(4),
+                B(CreateCatchContext), R(4), U8(6),
+                B(Star), R(3),
+                B(LdaTheHole),
+                B(SetPendingMessage),
+                B(Ldar), R(3),
+                B(PushContext), R(4),
+                B(LdaImmutableCurrentContextSlot), U8(4),
+                B(Star), R(6),
+                B(LdaTrue),
+                B(Star), R(7),
+                B(Mov), R(0), R(5),
+                B(InvokeIntrinsic), U8(Runtime::k_AsyncFunctionReject), R(5), U8(3),
+  /*   21 S> */ B(Return),
+]
+constant pool: [
+  Smi [36],
+  Smi [90],
+  SCOPE_INFO_TYPE,
+  Smi [10],
+  Smi [7],
+  ONE_BYTE_INTERNALIZED_STRING_TYPE ["foo"],
+  SCOPE_INFO_TYPE,
+]
+handlers: [
+  [64, 124, 124],
+]
+
+---
+snippet: "
+  await 42;
+  async function foo() {
+    await 42;
+  }
+  foo();
+"
+frame size: 9
+parameter count: 2
+bytecode array length: 153
+bytecodes: [
+                B(SwitchOnGeneratorState), R(0), U8(0), U8(2),
+                B(LdaConstant), U8(2),
+                B(Star), R(4),
+                B(Mov), R(arg0), R(3),
+                B(CallRuntime), U16(Runtime::kPushModuleContext), R(3), U8(2),
+                B(PushContext), R(3),
+                B(Mov), R(closure), R(4),
+                B(Mov), R(this), R(5),
+                B(InvokeIntrinsic), U8(Runtime::k_AsyncFunctionEnter), R(4), U8(2),
+                B(Star), R(0),
+                B(CreateClosure), U8(3), U8(0), U8(0),
+                B(Star), R(1),
+  /*    0 E> */ B(StackCheck),
+                B(Ldar), R(0),
+  /*    0 E> */ B(SuspendGenerator), R(0), R(0), U8(4), U8(0),
+                B(ResumeGenerator), R(0), R(0), U8(4),
+                B(Star), R(4),
+                B(InvokeIntrinsic), U8(Runtime::k_GeneratorGetResumeMode), R(0), U8(1),
+                B(SwitchOnSmiNoFeedback), U8(4), U8(2), I8(0),
+                B(Ldar), R(4),
+  /*    0 E> */ B(Throw),
+                B(Ldar), R(4),
+  /*   54 S> */ B(Return),
+                B(Mov), R(4), R(2),
+                B(Ldar), R(2),
+                B(Mov), R(context), R(4),
+  /*    0 S> */ B(LdaSmi), I8(42),
+                B(Star), R(6),
+                B(Mov), R(0), R(5),
+                B(InvokeIntrinsic), U8(Runtime::k_AsyncFunctionAwaitUncaught), R(5), U8(2),
+  /*    0 E> */ B(SuspendGenerator), R(0), R(0), U8(5), U8(1),
+                B(ResumeGenerator), R(0), R(0), U8(5),
+                B(Star), R(5),
+                B(InvokeIntrinsic), U8(Runtime::k_GeneratorGetResumeMode), R(0), U8(1),
+                B(Star), R(6),
+                B(LdaZero),
+                B(TestReferenceEqual), R(6),
+                B(JumpIfTrue), U8(5),
+                B(Ldar), R(5),
+                B(ReThrow),
+  /*   47 S> */ B(CallUndefinedReceiver0), R(1), U8(0),
+                B(LdaUndefined),
+                B(Star), R(6),
+                B(LdaTrue),
+                B(Star), R(7),
+                B(Mov), R(0), R(5),
+                B(InvokeIntrinsic), U8(Runtime::k_AsyncFunctionResolve), R(5), U8(3),
+  /*   54 S> */ B(Return),
+                B(Star), R(5),
+                B(CreateCatchContext), R(5), U8(6),
+                B(Star), R(4),
+                B(LdaTheHole),
+                B(SetPendingMessage),
+                B(Ldar), R(4),
+                B(PushContext), R(5),
+                B(LdaImmutableCurrentContextSlot), U8(4),
+                B(Star), R(7),
+                B(LdaTrue),
+                B(Star), R(8),
+                B(Mov), R(0), R(6),
+                B(InvokeIntrinsic), U8(Runtime::k_AsyncFunctionReject), R(6), U8(3),
+  /*   54 S> */ B(Return),
+]
+constant pool: [
+  Smi [44],
+  Smi [88],
+  SCOPE_INFO_TYPE,
+  SHARED_FUNCTION_INFO_TYPE,
+  Smi [10],
+  Smi [7],
+  SCOPE_INFO_TYPE,
+]
+handlers: [
+  [72, 125, 125],
+]
+
+---
+snippet: "
+  import * as foo from \"bar\";
+  await import(\"goo\");
+"
+frame size: 9
+parameter count: 2
+bytecode array length: 164
+bytecodes: [
+                B(SwitchOnGeneratorState), R(0), U8(0), U8(2),
+                B(LdaConstant), U8(2),
+                B(Star), R(4),
+                B(Mov), R(arg0), R(3),
+                B(CallRuntime), U16(Runtime::kPushModuleContext), R(3), U8(2),
+                B(PushContext), R(3),
+                B(Mov), R(closure), R(4),
+                B(Mov), R(this), R(5),
+                B(InvokeIntrinsic), U8(Runtime::k_AsyncFunctionEnter), R(4), U8(2),
+                B(Star), R(0),
+                B(LdaZero),
+                B(Star), R(4),
+                B(CallRuntime), U16(Runtime::kGetModuleNamespace), R(4), U8(1),
+                B(Star), R(1),
+  /*    0 E> */ B(StackCheck),
+                B(Ldar), R(0),
+  /*    0 E> */ B(SuspendGenerator), R(0), R(0), U8(4), U8(0),
+                B(ResumeGenerator), R(0), R(0), U8(4),
+                B(Star), R(4),
+                B(InvokeIntrinsic), U8(Runtime::k_GeneratorGetResumeMode), R(0), U8(1),
+                B(SwitchOnSmiNoFeedback), U8(3), U8(2), I8(0),
+                B(Ldar), R(4),
+  /*    0 E> */ B(Throw),
+                B(Ldar), R(4),
+  /*   49 S> */ B(Return),
+                B(Mov), R(4), R(2),
+                B(Ldar), R(2),
+                B(Mov), R(context), R(4),
+  /*   28 S> */ B(LdaConstant), U8(5),
+                B(Star), R(6),
+                B(Mov), R(closure), R(5),
+                B(CallRuntime), U16(Runtime::kDynamicImportCall), R(5), U8(2),
+                B(Star), R(6),
+                B(Mov), R(0), R(5),
+                B(InvokeIntrinsic), U8(Runtime::k_AsyncFunctionAwaitUncaught), R(5), U8(2),
+  /*   28 E> */ B(SuspendGenerator), R(0), R(0), U8(5), U8(1),
+                B(ResumeGenerator), R(0), R(0), U8(5),
+                B(Star), R(5),
+                B(InvokeIntrinsic), U8(Runtime::k_GeneratorGetResumeMode), R(0), U8(1),
+                B(Star), R(6),
+                B(LdaZero),
+                B(TestReferenceEqual), R(6),
+                B(JumpIfTrue), U8(5),
+                B(Ldar), R(5),
+                B(ReThrow),
+                B(LdaUndefined),
+                B(Star), R(6),
+                B(LdaTrue),
+                B(Star), R(7),
+                B(Mov), R(0), R(5),
+                B(InvokeIntrinsic), U8(Runtime::k_AsyncFunctionResolve), R(5), U8(3),
+  /*   49 S> */ B(Return),
+                B(Star), R(5),
+                B(CreateCatchContext), R(5), U8(6),
+                B(Star), R(4),
+                B(LdaTheHole),
+                B(SetPendingMessage),
+                B(Ldar), R(4),
+                B(PushContext), R(5),
+                B(LdaImmutableCurrentContextSlot), U8(4),
+                B(Star), R(7),
+                B(LdaTrue),
+                B(Star), R(8),
+                B(Mov), R(0), R(6),
+                B(InvokeIntrinsic), U8(Runtime::k_AsyncFunctionReject), R(6), U8(3),
+  /*   49 S> */ B(Return),
+]
+constant pool: [
+  Smi [48],
+  Smi [102],
+  SCOPE_INFO_TYPE,
+  Smi [10],
+  Smi [7],
+  ONE_BYTE_INTERNALIZED_STRING_TYPE ["goo"],
+  SCOPE_INFO_TYPE,
+]
+handlers: [
+  [76, 136, 136],
+]
+
diff --git a/test/cctest/interpreter/generate-bytecode-expectations.cc b/test/cctest/interpreter/generate-bytecode-expectations.cc
index a571e37..2fe3658 100644
--- a/test/cctest/interpreter/generate-bytecode-expectations.cc
+++ b/test/cctest/interpreter/generate-bytecode-expectations.cc
@@ -47,6 +47,7 @@
         oneshot_opt_(false),
         async_iteration_(false),
         private_methods_(false),
+        top_level_await_(false),
         verbose_(false) {}
 
   bool Validate() const;
@@ -70,6 +71,7 @@
   bool oneshot_opt() const { return oneshot_opt_; }
   bool async_iteration() const { return async_iteration_; }
   bool private_methods() const { return private_methods_; }
+  bool top_level_await() const { return top_level_await_; }
   bool verbose() const { return verbose_; }
   bool suppress_runtime_errors() const { return baseline() && !verbose_; }
   std::vector<std::string> input_filenames() const { return input_filenames_; }
@@ -90,6 +92,7 @@
   bool oneshot_opt_;
   bool async_iteration_;
   bool private_methods_;
+  bool top_level_await_;
   bool verbose_;
   std::vector<std::string> input_filenames_;
   std::string output_filename_;
@@ -196,6 +199,8 @@
       options.async_iteration_ = true;
     } else if (strcmp(argv[i], "--private-methods") == 0) {
       options.private_methods_ = true;
+    } else if (strcmp(argv[i], "--harmony-top-level-await") == 0) {
+      options.top_level_await_ = true;
     } else if (strcmp(argv[i], "--verbose") == 0) {
       options.verbose_ = true;
     } else if (strncmp(argv[i], "--output=", 9) == 0) {
@@ -318,6 +323,8 @@
       async_iteration_ = ParseBoolean(line.c_str() + 17);
     } else if (line.compare(0, 17, "private methods: ") == 0) {
       private_methods_ = ParseBoolean(line.c_str() + 17);
+    } else if (line.compare(0, 17, "top level await: ") == 0) {
+      top_level_await_ = ParseBoolean(line.c_str() + 17);
     } else if (line == "---") {
       break;
     } else if (line.empty()) {
@@ -342,6 +349,7 @@
   if (oneshot_opt_) *stream << "\noneshot opt: yes";
   if (async_iteration_) *stream << "\nasync iteration: yes";
   if (private_methods_) *stream << "\nprivate methods: yes";
+  if (top_level_await_) *stream << "\ntop level await: yes";
 
   *stream << "\n\n";
 }
@@ -451,6 +459,7 @@
   }
 
   if (options.private_methods()) i::FLAG_harmony_private_methods = true;
+  if (options.top_level_await()) i::FLAG_harmony_top_level_await = true;
 
   *stream << "#\n# Autogenerated by generate-bytecode-expectations.\n#\n\n";
   options.PrintHeader(stream);
@@ -459,6 +468,7 @@
   }
 
   i::FLAG_harmony_private_methods = false;
+  i::FLAG_harmony_top_level_await = false;
 }
 
 bool WriteExpectationsFile(const std::vector<std::string>& snippet_list,
@@ -519,6 +529,7 @@
          "Specify the name of the test function.\n"
          "  --top-level   Process top level code, not the top-level function.\n"
          "  --private-methods  Enable harmony_private_methods flag.\n"
+         "  --top-level-await  Enable await at the module level.\n"
          "  --output=file.name\n"
          "      Specify the output file. If not specified, output goes to "
          "stdout.\n"
diff --git a/test/cctest/interpreter/test-bytecode-generator.cc b/test/cctest/interpreter/test-bytecode-generator.cc
index 0f6c2f7..e8cbc6b 100644
--- a/test/cctest/interpreter/test-bytecode-generator.cc
+++ b/test/cctest/interpreter/test-bytecode-generator.cc
@@ -3142,6 +3142,35 @@
                      LoadGolden("Modules.golden")));
 }
 
+TEST(AsyncModules) {
+  bool previous_top_level_await_flag = i::FLAG_harmony_top_level_await;
+  i::FLAG_harmony_top_level_await = true;
+  InitializedIgnitionHandleScope scope;
+  BytecodeExpectationsPrinter printer(CcTest::isolate());
+  printer.set_wrap(false);
+  printer.set_module(true);
+  printer.set_top_level(true);
+
+  const char* snippets[] = {
+      "await 42;\n",
+
+      "await import(\"foo\");\n",
+
+      "await 42;\n"
+      "async function foo() {\n"
+      "  await 42;\n"
+      "}\n"
+      "foo();\n",
+
+      "import * as foo from \"bar\";\n"
+      "await import(\"goo\");\n",
+  };
+
+  CHECK(CompareTexts(BuildActual(printer, snippets),
+                     LoadGolden("AsyncModules.golden")));
+  i::FLAG_harmony_top_level_await = previous_top_level_await_flag;
+}
+
 TEST(SuperCallAndSpread) {
   InitializedIgnitionHandleScope scope;
   BytecodeExpectationsPrinter printer(CcTest::isolate());
diff --git a/test/cctest/test-modules.cc b/test/cctest/test-modules.cc
index f20aaed..d7cb6e6 100644
--- a/test/cctest/test-modules.cc
+++ b/test/cctest/test-modules.cc
@@ -659,4 +659,231 @@
   }
   i::FLAG_harmony_top_level_await = prev_top_level_await;
 }
+
+TEST(ModuleEvaluationTopLevelAwait) {
+  bool previous_top_level_await_flag_value = i::FLAG_harmony_top_level_await;
+  i::FLAG_harmony_top_level_await = true;
+  Isolate* isolate = CcTest::isolate();
+  HandleScope scope(isolate);
+  LocalContext env;
+  v8::TryCatch try_catch(isolate);
+  const char* sources[] = {
+      "await 42",
+      "import 'await 42';",
+      "import '42'; import 'await 42';",
+  };
+
+  for (auto src : sources) {
+    Local<String> source_text = v8_str(src);
+    ScriptOrigin origin = ModuleOrigin(v8_str("file.js"), CcTest::isolate());
+    ScriptCompiler::Source source(source_text, origin);
+    Local<Module> module =
+        ScriptCompiler::CompileModule(isolate, &source).ToLocalChecked();
+    CHECK_EQ(Module::kUninstantiated, module->GetStatus());
+    CHECK(module
+              ->InstantiateModule(env.local(),
+                                  CompileSpecifierAsModuleResolveCallback)
+              .FromJust());
+    CHECK_EQ(Module::kInstantiated, module->GetStatus());
+    Local<Promise> promise =
+        Local<Promise>::Cast(module->Evaluate(env.local()).ToLocalChecked());
+    CHECK_EQ(Module::kEvaluated, module->GetStatus());
+    CHECK_EQ(promise->State(), v8::Promise::kFulfilled);
+    CHECK(promise->Result()->IsUndefined());
+    CHECK(!try_catch.HasCaught());
+  }
+  i::FLAG_harmony_top_level_await = previous_top_level_await_flag_value;
+}
+
+TEST(ModuleEvaluationTopLevelAwaitError) {
+  bool previous_top_level_await_flag_value = i::FLAG_harmony_top_level_await;
+  i::FLAG_harmony_top_level_await = true;
+  Isolate* isolate = CcTest::isolate();
+  HandleScope scope(isolate);
+  LocalContext env;
+  const char* sources[] = {
+      "await 42; throw 'boom';",
+      "import 'await 42; throw \"boom\";';",
+      "import '42'; import 'await 42; throw \"boom\";';",
+  };
+
+  for (auto src : sources) {
+    v8::TryCatch try_catch(isolate);
+    Local<String> source_text = v8_str(src);
+    ScriptOrigin origin = ModuleOrigin(v8_str("file.js"), CcTest::isolate());
+    ScriptCompiler::Source source(source_text, origin);
+    Local<Module> module =
+        ScriptCompiler::CompileModule(isolate, &source).ToLocalChecked();
+    CHECK_EQ(Module::kUninstantiated, module->GetStatus());
+    CHECK(module
+              ->InstantiateModule(env.local(),
+                                  CompileSpecifierAsModuleResolveCallback)
+              .FromJust());
+    CHECK_EQ(Module::kInstantiated, module->GetStatus());
+    Local<Promise> promise =
+        Local<Promise>::Cast(module->Evaluate(env.local()).ToLocalChecked());
+    CHECK_EQ(Module::kErrored, module->GetStatus());
+    CHECK_EQ(promise->State(), v8::Promise::kRejected);
+    CHECK(promise->Result()->StrictEquals(v8_str("boom")));
+    CHECK(module->GetException()->StrictEquals(v8_str("boom")));
+
+    // TODO(joshualitt) I am not sure, but this might not be supposed to throw
+    // because it is async.
+    CHECK(!try_catch.HasCaught());
+  }
+  i::FLAG_harmony_top_level_await = previous_top_level_await_flag_value;
+}
+
+namespace {
+struct DynamicImportData {
+  DynamicImportData(Isolate* isolate_, Local<Promise::Resolver> resolver_,
+                    Local<Context> context_, bool should_resolve_)
+      : isolate(isolate_), should_resolve(should_resolve_) {
+    resolver.Reset(isolate, resolver_);
+    context.Reset(isolate, context_);
+  }
+
+  Isolate* isolate;
+  v8::Global<Promise::Resolver> resolver;
+  v8::Global<Context> context;
+  bool should_resolve;
+};
+
+void DoHostImportModuleDynamically(void* import_data) {
+  std::unique_ptr<DynamicImportData> import_data_(
+      static_cast<DynamicImportData*>(import_data));
+  Isolate* isolate(import_data_->isolate);
+  HandleScope handle_scope(isolate);
+
+  Local<Promise::Resolver> resolver(import_data_->resolver.Get(isolate));
+  Local<Context> realm(import_data_->context.Get(isolate));
+  Context::Scope context_scope(realm);
+
+  if (import_data_->should_resolve) {
+    resolver->Resolve(realm, True(isolate)).ToChecked();
+  } else {
+    resolver->Reject(realm, v8_str("boom")).ToChecked();
+  }
+}
+
+v8::MaybeLocal<v8::Promise> HostImportModuleDynamicallyCallbackResolve(
+    Local<Context> context, Local<v8::ScriptOrModule> referrer,
+    Local<String> specifier) {
+  Isolate* isolate = context->GetIsolate();
+  Local<v8::Promise::Resolver> resolver =
+      v8::Promise::Resolver::New(context).ToLocalChecked();
+
+  DynamicImportData* data =
+      new DynamicImportData(isolate, resolver, context, true);
+  isolate->EnqueueMicrotask(DoHostImportModuleDynamically, data);
+  return resolver->GetPromise();
+}
+
+v8::MaybeLocal<v8::Promise> HostImportModuleDynamicallyCallbackReject(
+    Local<Context> context, Local<v8::ScriptOrModule> referrer,
+    Local<String> specifier) {
+  Isolate* isolate = context->GetIsolate();
+  Local<v8::Promise::Resolver> resolver =
+      v8::Promise::Resolver::New(context).ToLocalChecked();
+
+  DynamicImportData* data =
+      new DynamicImportData(isolate, resolver, context, false);
+  isolate->EnqueueMicrotask(DoHostImportModuleDynamically, data);
+  return resolver->GetPromise();
+}
+
+}  // namespace
+
+TEST(ModuleEvaluationTopLevelAwaitDynamicImport) {
+  bool previous_top_level_await_flag_value = i::FLAG_harmony_top_level_await;
+  bool previous_dynamic_import_flag_value = i::FLAG_harmony_dynamic_import;
+  i::FLAG_harmony_top_level_await = true;
+  i::FLAG_harmony_dynamic_import = true;
+  Isolate* isolate = CcTest::isolate();
+  HandleScope scope(isolate);
+  isolate->SetMicrotasksPolicy(v8::MicrotasksPolicy::kExplicit);
+  isolate->SetHostImportModuleDynamicallyCallback(
+      HostImportModuleDynamicallyCallbackResolve);
+  LocalContext env;
+  v8::TryCatch try_catch(isolate);
+  const char* sources[] = {
+      "await import('foo');",
+      "import 'await import(\"foo\");';",
+      "import '42'; import 'await import(\"foo\");';",
+  };
+
+  for (auto src : sources) {
+    Local<String> source_text = v8_str(src);
+    ScriptOrigin origin = ModuleOrigin(v8_str("file.js"), CcTest::isolate());
+    ScriptCompiler::Source source(source_text, origin);
+    Local<Module> module =
+        ScriptCompiler::CompileModule(isolate, &source).ToLocalChecked();
+    CHECK_EQ(Module::kUninstantiated, module->GetStatus());
+    CHECK(module
+              ->InstantiateModule(env.local(),
+                                  CompileSpecifierAsModuleResolveCallback)
+              .FromJust());
+    CHECK_EQ(Module::kInstantiated, module->GetStatus());
+
+    Local<Promise> promise =
+        Local<Promise>::Cast(module->Evaluate(env.local()).ToLocalChecked());
+    CHECK_EQ(Module::kEvaluated, module->GetStatus());
+    CHECK_EQ(promise->State(), v8::Promise::kPending);
+    CHECK(!try_catch.HasCaught());
+
+    isolate->RunMicrotasks();
+    CHECK_EQ(promise->State(), v8::Promise::kFulfilled);
+  }
+  i::FLAG_harmony_top_level_await = previous_top_level_await_flag_value;
+  i::FLAG_harmony_dynamic_import = previous_dynamic_import_flag_value;
+}
+
+TEST(ModuleEvaluationTopLevelAwaitDynamicImportError) {
+  bool previous_top_level_await_flag_value = i::FLAG_harmony_top_level_await;
+  bool previous_dynamic_import_flag_value = i::FLAG_harmony_dynamic_import;
+  i::FLAG_harmony_top_level_await = true;
+  i::FLAG_harmony_dynamic_import = true;
+  Isolate* isolate = CcTest::isolate();
+  HandleScope scope(isolate);
+  isolate->SetMicrotasksPolicy(v8::MicrotasksPolicy::kExplicit);
+  isolate->SetHostImportModuleDynamicallyCallback(
+      HostImportModuleDynamicallyCallbackReject);
+  LocalContext env;
+  v8::TryCatch try_catch(isolate);
+  const char* sources[] = {
+      "await import('foo');",
+      "import 'await import(\"foo\");';",
+      "import '42'; import 'await import(\"foo\");';",
+  };
+
+  for (auto src : sources) {
+    Local<String> source_text = v8_str(src);
+    ScriptOrigin origin = ModuleOrigin(v8_str("file.js"), CcTest::isolate());
+    ScriptCompiler::Source source(source_text, origin);
+    Local<Module> module =
+        ScriptCompiler::CompileModule(isolate, &source).ToLocalChecked();
+    CHECK_EQ(Module::kUninstantiated, module->GetStatus());
+    CHECK(module
+              ->InstantiateModule(env.local(),
+                                  CompileSpecifierAsModuleResolveCallback)
+              .FromJust());
+    CHECK_EQ(Module::kInstantiated, module->GetStatus());
+
+    Local<Promise> promise =
+        Local<Promise>::Cast(module->Evaluate(env.local()).ToLocalChecked());
+    CHECK_EQ(Module::kEvaluated, module->GetStatus());
+    CHECK_EQ(promise->State(), v8::Promise::kPending);
+    CHECK(!try_catch.HasCaught());
+
+    isolate->RunMicrotasks();
+    CHECK_EQ(Module::kErrored, module->GetStatus());
+    CHECK_EQ(promise->State(), v8::Promise::kRejected);
+    CHECK(promise->Result()->StrictEquals(v8_str("boom")));
+    CHECK(module->GetException()->StrictEquals(v8_str("boom")));
+    CHECK(!try_catch.HasCaught());
+  }
+  i::FLAG_harmony_top_level_await = previous_top_level_await_flag_value;
+  i::FLAG_harmony_dynamic_import = previous_dynamic_import_flag_value;
+}
+
 }  // anonymous namespace
diff --git a/test/message/fail/modules-import-top-level-await-fail-1.mjs b/test/message/fail/modules-import-top-level-await-fail-1.mjs
new file mode 100644
index 0000000..3a00ba6
--- /dev/null
+++ b/test/message/fail/modules-import-top-level-await-fail-1.mjs
@@ -0,0 +1,9 @@
+// Copyright 2019 the V8 project authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+// MODULE
+//
+// Flags: --harmony-top-level-await
+
+import "modules-skip-1-top-level-await-fail.mjs"
diff --git a/test/message/fail/modules-import-top-level-await-fail-1.out b/test/message/fail/modules-import-top-level-await-fail-1.out
new file mode 100644
index 0000000..2b2cb40
--- /dev/null
+++ b/test/message/fail/modules-import-top-level-await-fail-1.out
@@ -0,0 +1,3 @@
+*modules-skip-1-top-level-await-fail.mjs:7: ReferenceError: x is not defined
+await x;
+^
diff --git a/test/message/fail/modules-import-top-level-await-fail-2.mjs b/test/message/fail/modules-import-top-level-await-fail-2.mjs
new file mode 100644
index 0000000..c0bc4c2
--- /dev/null
+++ b/test/message/fail/modules-import-top-level-await-fail-2.mjs
@@ -0,0 +1,9 @@
+// Copyright 2019 the V8 project authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+// MODULE
+//
+// Flags: --harmony-top-level-await
+
+import "modules-skip-2-top-level-await-fail.mjs"
diff --git a/test/message/fail/modules-import-top-level-await-fail-2.out b/test/message/fail/modules-import-top-level-await-fail-2.out
new file mode 100644
index 0000000..208d53e
--- /dev/null
+++ b/test/message/fail/modules-import-top-level-await-fail-2.out
@@ -0,0 +1,3 @@
+*modules-skip-2-top-level-await-fail.mjs:7: ReferenceError: ththsths is not defined
+ththsths
+^
diff --git a/test/message/fail/modules-skip-1-top-level-await-fail.mjs b/test/message/fail/modules-skip-1-top-level-await-fail.mjs
new file mode 100644
index 0000000..0642ddf
--- /dev/null
+++ b/test/message/fail/modules-skip-1-top-level-await-fail.mjs
@@ -0,0 +1,7 @@
+// Copyright 2019 the V8 project authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+// MODULE
+
+await x;
diff --git a/test/message/fail/modules-skip-2-top-level-await-fail.mjs b/test/message/fail/modules-skip-2-top-level-await-fail.mjs
new file mode 100644
index 0000000..19edc2c
--- /dev/null
+++ b/test/message/fail/modules-skip-2-top-level-await-fail.mjs
@@ -0,0 +1,7 @@
+// Copyright 2019 the V8 project authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+import "modules-skip-3-top-level-await-fail.mjs"
+
+ththsths
diff --git a/test/message/fail/modules-skip-3-top-level-await-fail.mjs b/test/message/fail/modules-skip-3-top-level-await-fail.mjs
new file mode 100644
index 0000000..caf3431
--- /dev/null
+++ b/test/message/fail/modules-skip-3-top-level-await-fail.mjs
@@ -0,0 +1,5 @@
+// Copyright 2019 the V8 project authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+await 42;
diff --git a/test/mjsunit/harmony/modules-import-15-top-level-await.mjs b/test/mjsunit/harmony/modules-import-15-top-level-await.mjs
new file mode 100644
index 0000000..1feb3da
--- /dev/null
+++ b/test/mjsunit/harmony/modules-import-15-top-level-await.mjs
@@ -0,0 +1,58 @@
+// Copyright 2019 the V8 project authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+// Flags: --harmony-top-level-await --allow-natives-syntax
+// Flags: --harmony-dynamic-import
+
+var ran = false;
+
+async function test1() {
+  try {
+    let x = await import('modules-skip-8.mjs');
+    %AbortJS('failure: should be unreachable');
+  } catch(e) {
+    assertEquals('x is not defined', e.message);
+    ran = true;
+  }
+}
+
+test1();
+%PerformMicrotaskCheckpoint();
+assertTrue(ran);
+
+ran = false;
+
+async function test2() {
+  try {
+    let x = await import('modules-skip-9.mjs');
+    %AbortJS('failure: should be unreachable');
+  } catch(e) {
+    assertInstanceof(e, SyntaxError);
+    assertEquals(
+      "The requested module 'modules-skip-empty.mjs' does not provide an " +
+      "export named 'default'",
+      e.message);
+    ran = true;
+  }
+}
+
+test2();
+%PerformMicrotaskCheckpoint();
+assertTrue(ran);
+
+ran = false;
+
+async function test3() {
+  try {
+    let x = await import('nonexistent-file.mjs');
+    %AbortJS('failure: should be unreachable');
+  } catch(e) {
+    assertTrue(e.startsWith('Error reading'));
+    ran = true;
+  }
+}
+
+test3();
+%PerformMicrotaskCheckpoint();
+assertTrue(ran);
diff --git a/test/mjsunit/harmony/modules-import-rqstd-order-top-level-await-1.mjs b/test/mjsunit/harmony/modules-import-rqstd-order-top-level-await-1.mjs
new file mode 100644
index 0000000..9c9dfc3
--- /dev/null
+++ b/test/mjsunit/harmony/modules-import-rqstd-order-top-level-await-1.mjs
@@ -0,0 +1,12 @@
+// Copyright 2019 the V8 project authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+// Flags: --harmony-top-level-await
+
+assertEquals(globalThis.test262, ['1', '2', '3', '4']);
+
+import 'modules-skip-1-rqstd-order.mjs';
+import 'modules-skip-2-rqstd-order.mjs';
+import 'modules-skip-3-rqstd-order.mjs';
+import 'modules-skip-4-rqstd-order.mjs';
diff --git a/test/mjsunit/harmony/modules-import-rqstd-order-top-level-await-2.mjs b/test/mjsunit/harmony/modules-import-rqstd-order-top-level-await-2.mjs
new file mode 100644
index 0000000..374660e
--- /dev/null
+++ b/test/mjsunit/harmony/modules-import-rqstd-order-top-level-await-2.mjs
@@ -0,0 +1,15 @@
+// Copyright 2019 the V8 project authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+// Flags: --harmony-top-level-await
+
+assertEquals(globalThis.test262, [
+  '1_dir_a', '2_dir_a', '3_dir_a', '4_dir_a',
+  '1', '2', '3', '4',
+  '1_dir_b', '2_dir_b', '3_dir_b', '4_dir_b']);
+
+import 'modules-skip-1-rqstd-order-top-level-await.mjs';
+import 'modules-skip-2-rqstd-order-top-level-await.mjs';
+import 'modules-skip-3-rqstd-order-top-level-await.mjs';
+import 'modules-skip-4-rqstd-order-top-level-await.mjs';
diff --git a/test/mjsunit/harmony/modules-import-rqstd-order-top-level-await-3.mjs b/test/mjsunit/harmony/modules-import-rqstd-order-top-level-await-3.mjs
new file mode 100644
index 0000000..f145a75
--- /dev/null
+++ b/test/mjsunit/harmony/modules-import-rqstd-order-top-level-await-3.mjs
@@ -0,0 +1,13 @@
+// Copyright 2019 the V8 project authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+// Flags: --harmony-top-level-await
+
+assertEquals(globalThis.test262, [
+  '1', '2_dir_a', '3', '4_dir_a', '2', '4', '2_dir_b', '4_dir_b']);
+
+import 'modules-skip-1-rqstd-order.mjs';
+import 'modules-skip-2-rqstd-order-top-level-await.mjs';
+import 'modules-skip-3-rqstd-order.mjs';
+import 'modules-skip-4-rqstd-order-top-level-await.mjs';
diff --git a/test/mjsunit/harmony/modules-import-rqstd-order-top-level-await-4.mjs b/test/mjsunit/harmony/modules-import-rqstd-order-top-level-await-4.mjs
new file mode 100644
index 0000000..57e6e54
--- /dev/null
+++ b/test/mjsunit/harmony/modules-import-rqstd-order-top-level-await-4.mjs
@@ -0,0 +1,17 @@
+// Copyright 2019 the V8 project authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+// Flags: --harmony-top-level-await
+
+assertEquals(globalThis.test262, [
+  '1_dir_a', '2_dir_a', '3_dir_a', '4_dir_a',
+  '1', '2', '3', '4',
+  '1_dir_b', '2_dir_b', '3_dir_b', '4_dir_b',
+  '1_ind', '2_ind', '3_ind', '4_ind',
+]);
+
+import 'modules-skip-1-rqstd-order-indirect-top-level-await.mjs';
+import 'modules-skip-2-rqstd-order-indirect-top-level-await.mjs';
+import 'modules-skip-3-rqstd-order-indirect-top-level-await.mjs';
+import 'modules-skip-4-rqstd-order-indirect-top-level-await.mjs';
diff --git a/test/mjsunit/harmony/modules-import-rqstd-order-top-level-await-5.mjs b/test/mjsunit/harmony/modules-import-rqstd-order-top-level-await-5.mjs
new file mode 100644
index 0000000..e018705
--- /dev/null
+++ b/test/mjsunit/harmony/modules-import-rqstd-order-top-level-await-5.mjs
@@ -0,0 +1,16 @@
+// Copyright 2019 the V8 project authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+// Flags: --harmony-top-level-await
+
+assertEquals(globalThis.test262, [
+  '1', '2_dir_a', '3_dir_a', '4',
+  '2', '3', '2_dir_b', '3_dir_b',
+  '2_ind',
+]);
+
+import 'modules-skip-1-rqstd-order.mjs';
+import 'modules-skip-2-rqstd-order-indirect-top-level-await.mjs';
+import 'modules-skip-3-rqstd-order-top-level-await.mjs';
+import 'modules-skip-4-rqstd-order.mjs';
diff --git a/test/mjsunit/harmony/modules-import-rqstd-order-top-level-await-6.mjs b/test/mjsunit/harmony/modules-import-rqstd-order-top-level-await-6.mjs
new file mode 100644
index 0000000..8d3ed1f
--- /dev/null
+++ b/test/mjsunit/harmony/modules-import-rqstd-order-top-level-await-6.mjs
@@ -0,0 +1,16 @@
+// Copyright 2019 the V8 project authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+// Flags: --harmony-top-level-await
+
+assertEquals(globalThis.test262, [
+  '1_dir_a', '2_dir_a', '3', '4_dir_a',
+  '1', '2', '4', '1_dir_b', '2_dir_b',
+  '4_dir_b', '2_ind',
+]);
+
+import 'modules-skip-1-rqstd-order-top-level-await.mjs';
+import 'modules-skip-2-rqstd-order-indirect-top-level-await.mjs';
+import 'modules-skip-3-rqstd-order.mjs';
+import 'modules-skip-4-rqstd-order-top-level-await.mjs';
diff --git a/test/mjsunit/harmony/modules-import-rqstd-order-top-level-await-7.mjs b/test/mjsunit/harmony/modules-import-rqstd-order-top-level-await-7.mjs
new file mode 100644
index 0000000..64bbeb1
--- /dev/null
+++ b/test/mjsunit/harmony/modules-import-rqstd-order-top-level-await-7.mjs
@@ -0,0 +1,12 @@
+// Copyright 2019 the V8 project authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+// Flags: --harmony-top-level-await
+
+assertEquals(globalThis.test262, [
+  '1_udir_a', '1_udir_b', '2',
+]);
+
+import 'modules-skip-1-rqstd-order-unreached-top-level-await.mjs';
+import 'modules-skip-2-rqstd-order.mjs';
diff --git a/test/mjsunit/harmony/modules-import-rqstd-order-top-level-await-8.mjs b/test/mjsunit/harmony/modules-import-rqstd-order-top-level-await-8.mjs
new file mode 100644
index 0000000..0d9fe3e
--- /dev/null
+++ b/test/mjsunit/harmony/modules-import-rqstd-order-top-level-await-8.mjs
@@ -0,0 +1,12 @@
+// Copyright 2019 the V8 project authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+// Flags: --harmony-top-level-await
+
+assertEquals(globalThis.test262, [
+  '1_udir_a', '1_udir_b', '2', '1_uind'
+]);
+
+import 'modules-skip-1-rqstd-order-indirect-unreached-top-level-await.mjs';
+import 'modules-skip-2-rqstd-order.mjs';
diff --git a/test/mjsunit/harmony/modules-import-top-level-await-1.mjs b/test/mjsunit/harmony/modules-import-top-level-await-1.mjs
new file mode 100644
index 0000000..c8efa5d
--- /dev/null
+++ b/test/mjsunit/harmony/modules-import-top-level-await-1.mjs
@@ -0,0 +1,14 @@
+// Copyright 2019 the V8 project authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+// Flags: --allow-natives-syntax --harmony-dynamic-import --harmony-top-level-await
+
+let promise_resolved = false;
+let m = import('modules-skip-1.mjs');
+m.then(
+  () => { promise_resolved = true; },
+  () => { %AbortJS('Promise rejected'); });
+await m;
+
+assertEquals(promise_resolved, true);
diff --git a/test/mjsunit/harmony/modules-import-top-level-await-2.mjs b/test/mjsunit/harmony/modules-import-top-level-await-2.mjs
new file mode 100644
index 0000000..0f74aa7
--- /dev/null
+++ b/test/mjsunit/harmony/modules-import-top-level-await-2.mjs
@@ -0,0 +1,10 @@
+// Copyright 2019 the V8 project authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+// Flags: --harmony-dynamic-import --harmony-top-level-await
+
+let m = import('modules-skip-1.mjs');
+let m_namespace = await m;
+
+assertEquals(42, m_namespace.life());
diff --git a/test/mjsunit/harmony/modules-import-top-level-await-3.mjs b/test/mjsunit/harmony/modules-import-top-level-await-3.mjs
new file mode 100644
index 0000000..44c8145
--- /dev/null
+++ b/test/mjsunit/harmony/modules-import-top-level-await-3.mjs
@@ -0,0 +1,14 @@
+// Copyright 2019 the V8 project authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+// Flags: --harmony-dynamic-import --harmony-top-level-await
+
+let m1 = import('modules-skip-1.mjs');
+let m1_namespace = await m1;
+
+let m2 = import('modules-skip-3.mjs');
+let m2_namespace = await m2;
+
+assertEquals(42, m1_namespace.life());
+assertEquals('42', m2_namespace.stringlife);
diff --git a/test/mjsunit/harmony/modules-import-top-level-await-4.mjs b/test/mjsunit/harmony/modules-import-top-level-await-4.mjs
new file mode 100644
index 0000000..29730fa
--- /dev/null
+++ b/test/mjsunit/harmony/modules-import-top-level-await-4.mjs
@@ -0,0 +1,9 @@
+// Copyright 2019 the V8 project authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+// Flags: --harmony-dynamic-import --harmony-top-level-await
+
+import * as m from 'modules-skip-1-top-level-await.mjs'
+
+assertEquals(42, m.life());
diff --git a/test/mjsunit/harmony/modules-import-top-level-await-5.mjs b/test/mjsunit/harmony/modules-import-top-level-await-5.mjs
new file mode 100644
index 0000000..f1e7813
--- /dev/null
+++ b/test/mjsunit/harmony/modules-import-top-level-await-5.mjs
@@ -0,0 +1,10 @@
+// Copyright 2019 the V8 project authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+// Flags: --harmony-dynamic-import --harmony-top-level-await
+
+import * as m from 'modules-skip-2-top-level-await.mjs'
+
+assertEquals(42, m.life());
+assertEquals('42', m.stringlife);
diff --git a/test/mjsunit/harmony/modules-import-top-level-await-6.mjs b/test/mjsunit/harmony/modules-import-top-level-await-6.mjs
new file mode 100644
index 0000000..f852895
--- /dev/null
+++ b/test/mjsunit/harmony/modules-import-top-level-await-6.mjs
@@ -0,0 +1,10 @@
+// Copyright 2019 the V8 project authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+// Flags: --harmony-dynamic-import --harmony-top-level-await
+
+import * as m from 'modules-skip-3-top-level-await.mjs'
+
+assertEquals(42, m.life());
+assertEquals('42', m.stringlife);
diff --git a/test/mjsunit/harmony/modules-import-top-level-await-7.mjs b/test/mjsunit/harmony/modules-import-top-level-await-7.mjs
new file mode 100644
index 0000000..26f1440
--- /dev/null
+++ b/test/mjsunit/harmony/modules-import-top-level-await-7.mjs
@@ -0,0 +1,9 @@
+// Copyright 2019 the V8 project authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+// Flags: --harmony-top-level-await --harmony-dynamic-import
+
+import * as m from 'modules-skip-6-top-level-await.mjs';
+
+assertEquals(m.m1.life(), m.m2.life());
diff --git a/test/mjsunit/harmony/modules-import-top-level-await-8.mjs b/test/mjsunit/harmony/modules-import-top-level-await-8.mjs
new file mode 100644
index 0000000..aa80c73
--- /dev/null
+++ b/test/mjsunit/harmony/modules-import-top-level-await-8.mjs
@@ -0,0 +1,9 @@
+// Copyright 2019 the V8 project authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+// Flags: --harmony-dynamic-import --harmony-top-level-await
+
+import * as m from 'modules-skip-7-top-level-await.mjs'
+
+assertEquals(42, m.life);
diff --git a/test/mjsunit/harmony/modules-import-top-level-await-cycle.mjs b/test/mjsunit/harmony/modules-import-top-level-await-cycle.mjs
new file mode 100644
index 0000000..0ec478e
--- /dev/null
+++ b/test/mjsunit/harmony/modules-import-top-level-await-cycle.mjs
@@ -0,0 +1,16 @@
+// Copyright 2019 the V8 project authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+// Flags: --harmony-top-level-await --harmony-dynamic-import
+
+import * as m1 from 'modules-skip-1-top-level-await-cycle.mjs'
+import * as m2 from 'modules-skip-2-top-level-await-cycle.mjs'
+import * as m3 from 'modules-skip-3-top-level-await-cycle.mjs'
+
+assertSame(m1.m1.m.m.life, m1.m2.m.m.life);
+assertSame(m1.m1.m.m.life, m2.m.m.life);
+assertSame(m1.m1.m.m.life, m3.m.m.life);
+
+let m4 = await import('modules-skip-1.mjs');
+assertSame(m1.m1.m.m.life, m4.life);
diff --git a/test/mjsunit/harmony/modules-import-top-level-await-exception-1.mjs b/test/mjsunit/harmony/modules-import-top-level-await-exception-1.mjs
new file mode 100644
index 0000000..1e22f15
--- /dev/null
+++ b/test/mjsunit/harmony/modules-import-top-level-await-exception-1.mjs
@@ -0,0 +1,18 @@
+// Copyright 2019 the V8 project authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+// Flags: --harmony-dynamic-import --harmony-top-level-await
+
+let ran = false;
+let m = import('modules-skip-2.mjs');
+await m.then(
+  () => {
+    assertUnreachable();
+  },
+  (e) => {
+    assertEquals(e.message, '42 is not the answer');
+    ran = true;
+  });
+
+assertEquals(ran, true);
diff --git a/test/mjsunit/harmony/modules-import-top-level-await-exception-2.mjs b/test/mjsunit/harmony/modules-import-top-level-await-exception-2.mjs
new file mode 100644
index 0000000..476cfbee
--- /dev/null
+++ b/test/mjsunit/harmony/modules-import-top-level-await-exception-2.mjs
@@ -0,0 +1,16 @@
+// Copyright 2019 the V8 project authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+// Flags: --harmony-dynamic-import --harmony-top-level-await
+
+let ran = false;
+try {
+  await import('modules-skip-2.mjs');
+  assertUnreachable();
+} catch (e) {
+  assertEquals(e.message, '42 is not the answer');
+  ran = true;
+}
+
+assertEquals(ran, true);
diff --git a/test/mjsunit/harmony/modules-import-top-level-await-exception-3.mjs b/test/mjsunit/harmony/modules-import-top-level-await-exception-3.mjs
new file mode 100644
index 0000000..20de7ef
--- /dev/null
+++ b/test/mjsunit/harmony/modules-import-top-level-await-exception-3.mjs
@@ -0,0 +1,16 @@
+// Copyright 2019 the V8 project authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+// Flags: --harmony-dynamic-import --harmony-top-level-await
+
+let ran = false;
+try {
+  await import('modules-skip-4-top-level-await.mjs');
+  assertUnreachable();
+} catch (e) {
+  assertEquals(e.message, '42 is not the answer');
+  ran = true;
+}
+
+assertEquals(ran, true);
diff --git a/test/mjsunit/harmony/modules-skip-1-rqstd-order-indirect-top-level-await.mjs b/test/mjsunit/harmony/modules-skip-1-rqstd-order-indirect-top-level-await.mjs
new file mode 100644
index 0000000..cbd357c
--- /dev/null
+++ b/test/mjsunit/harmony/modules-skip-1-rqstd-order-indirect-top-level-await.mjs
@@ -0,0 +1,6 @@
+// Copyright 2019 the V8 project authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+import 'modules-skip-1-rqstd-order-top-level-await.mjs'
+Function('return this;')().test262.push('1_ind');
diff --git a/test/mjsunit/harmony/modules-skip-1-rqstd-order-indirect-unreached-top-level-await.mjs b/test/mjsunit/harmony/modules-skip-1-rqstd-order-indirect-unreached-top-level-await.mjs
new file mode 100644
index 0000000..c6dff00
--- /dev/null
+++ b/test/mjsunit/harmony/modules-skip-1-rqstd-order-indirect-unreached-top-level-await.mjs
@@ -0,0 +1,8 @@
+// Copyright 2019 the V8 project authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+import 'modules-skip-1-rqstd-order-unreached-top-level-await.mjs';
+
+Function('return this;')().test262.push('1_uind');
+
diff --git a/test/mjsunit/harmony/modules-skip-1-rqstd-order-top-level-await.mjs b/test/mjsunit/harmony/modules-skip-1-rqstd-order-top-level-await.mjs
new file mode 100644
index 0000000..fcbe07a
--- /dev/null
+++ b/test/mjsunit/harmony/modules-skip-1-rqstd-order-top-level-await.mjs
@@ -0,0 +1,12 @@
+// Copyright 2019 the V8 project authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+if (typeof Function('return this;')().test262 === 'undefined') {
+  Function('return this;')().test262 = ['1_dir_a'];
+} else {
+  Function('return this;')().test262.push('1_dir_a');
+}
+let m = import('modules-skip-1-rqstd-order.mjs');
+await m;
+Function('return this;')().test262.push('1_dir_b');
diff --git a/test/mjsunit/harmony/modules-skip-1-rqstd-order-unreached-top-level-await.mjs b/test/mjsunit/harmony/modules-skip-1-rqstd-order-unreached-top-level-await.mjs
new file mode 100644
index 0000000..f2b2104
--- /dev/null
+++ b/test/mjsunit/harmony/modules-skip-1-rqstd-order-unreached-top-level-await.mjs
@@ -0,0 +1,14 @@
+// Copyright 2019 the V8 project authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+if (typeof Function('return this;')().test262 === 'undefined') {
+  Function('return this;')().test262 = ['1_udir_a'];
+} else {
+  Function('return this;')().test262.push('1_udir_a');
+}
+if (false) {
+  assertUnreachable();
+  await 42;
+}
+Function('return this;')().test262.push('1_udir_b');
diff --git a/test/mjsunit/harmony/modules-skip-1-rqstd-order.mjs b/test/mjsunit/harmony/modules-skip-1-rqstd-order.mjs
new file mode 100644
index 0000000..5ac1882
--- /dev/null
+++ b/test/mjsunit/harmony/modules-skip-1-rqstd-order.mjs
@@ -0,0 +1,9 @@
+// Copyright 2019 the V8 project authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+if (typeof Function('return this;')().test262 === 'undefined') {
+  Function('return this;')().test262 = ['1'];
+} else {
+  Function('return this;')().test262.push('1');
+}
diff --git a/test/mjsunit/harmony/modules-skip-1-top-level-await-cycle.mjs b/test/mjsunit/harmony/modules-skip-1-top-level-await-cycle.mjs
new file mode 100644
index 0000000..601e80a
--- /dev/null
+++ b/test/mjsunit/harmony/modules-skip-1-top-level-await-cycle.mjs
@@ -0,0 +1,8 @@
+// Copyright 2019 the V8 project authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+import * as m1 from 'modules-skip-2-top-level-await-cycle.mjs';
+import * as m2 from 'modules-skip-3-top-level-await-cycle.mjs';
+
+export { m1, m2 };
diff --git a/test/mjsunit/harmony/modules-skip-1-top-level-await.mjs b/test/mjsunit/harmony/modules-skip-1-top-level-await.mjs
new file mode 100644
index 0000000..25973fe
--- /dev/null
+++ b/test/mjsunit/harmony/modules-skip-1-top-level-await.mjs
@@ -0,0 +1,11 @@
+// Copyright 2019 the V8 project authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+let m = import('modules-skip-1.mjs');
+let m_namespace = await m;
+
+export function life() {
+  return m_namespace.life();
+}
+
diff --git a/test/mjsunit/harmony/modules-skip-2-rqstd-order-indirect-top-level-await.mjs b/test/mjsunit/harmony/modules-skip-2-rqstd-order-indirect-top-level-await.mjs
new file mode 100644
index 0000000..2305422
--- /dev/null
+++ b/test/mjsunit/harmony/modules-skip-2-rqstd-order-indirect-top-level-await.mjs
@@ -0,0 +1,6 @@
+// Copyright 2019 the V8 project authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+import 'modules-skip-2-rqstd-order-top-level-await.mjs'
+Function('return this;')().test262.push('2_ind');
diff --git a/test/mjsunit/harmony/modules-skip-2-rqstd-order-top-level-await.mjs b/test/mjsunit/harmony/modules-skip-2-rqstd-order-top-level-await.mjs
new file mode 100644
index 0000000..c2b20a5
--- /dev/null
+++ b/test/mjsunit/harmony/modules-skip-2-rqstd-order-top-level-await.mjs
@@ -0,0 +1,8 @@
+// Copyright 2019 the V8 project authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+Function('return this;')().test262.push('2_dir_a');
+let m = import('modules-skip-2-rqstd-order.mjs');
+await m;
+Function('return this;')().test262.push('2_dir_b');
diff --git a/test/mjsunit/harmony/modules-skip-2-rqstd-order.mjs b/test/mjsunit/harmony/modules-skip-2-rqstd-order.mjs
new file mode 100644
index 0000000..7dbd64c
--- /dev/null
+++ b/test/mjsunit/harmony/modules-skip-2-rqstd-order.mjs
@@ -0,0 +1,5 @@
+// Copyright 2019 the V8 project authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+Function('return this;')().test262.push('2');
diff --git a/test/mjsunit/harmony/modules-skip-2-top-level-await-cycle.mjs b/test/mjsunit/harmony/modules-skip-2-top-level-await-cycle.mjs
new file mode 100644
index 0000000..3171bb8
--- /dev/null
+++ b/test/mjsunit/harmony/modules-skip-2-top-level-await-cycle.mjs
@@ -0,0 +1,7 @@
+// Copyright 2019 the V8 project authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+import * as m from 'modules-skip-4-top-level-await-cycle.mjs';
+
+export { m };
diff --git a/test/mjsunit/harmony/modules-skip-2-top-level-await.mjs b/test/mjsunit/harmony/modules-skip-2-top-level-await.mjs
new file mode 100644
index 0000000..4aa2f2c
--- /dev/null
+++ b/test/mjsunit/harmony/modules-skip-2-top-level-await.mjs
@@ -0,0 +1,15 @@
+// Copyright 2019 the V8 project authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+import * as m1 from 'modules-skip-3.mjs'
+
+let m2 = import('modules-skip-1-top-level-await.mjs');
+let m2_namespace = await m2;
+
+export let stringlife = m1.stringlife;
+
+export function life() {
+  return m2_namespace.life();
+}
+
diff --git a/test/mjsunit/harmony/modules-skip-3-rqstd-order-indirect-top-level-await.mjs b/test/mjsunit/harmony/modules-skip-3-rqstd-order-indirect-top-level-await.mjs
new file mode 100644
index 0000000..2b4dae0
--- /dev/null
+++ b/test/mjsunit/harmony/modules-skip-3-rqstd-order-indirect-top-level-await.mjs
@@ -0,0 +1,6 @@
+// Copyright 2019 the V8 project authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+import 'modules-skip-3-rqstd-order-top-level-await.mjs'
+Function('return this;')().test262.push('3_ind');
diff --git a/test/mjsunit/harmony/modules-skip-3-rqstd-order-top-level-await.mjs b/test/mjsunit/harmony/modules-skip-3-rqstd-order-top-level-await.mjs
new file mode 100644
index 0000000..f3b8904
--- /dev/null
+++ b/test/mjsunit/harmony/modules-skip-3-rqstd-order-top-level-await.mjs
@@ -0,0 +1,8 @@
+// Copyright 2019 the V8 project authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+Function('return this;')().test262.push('3_dir_a');
+let m = import('modules-skip-3-rqstd-order.mjs');
+await m;
+Function('return this;')().test262.push('3_dir_b');
diff --git a/test/mjsunit/harmony/modules-skip-3-rqstd-order.mjs b/test/mjsunit/harmony/modules-skip-3-rqstd-order.mjs
new file mode 100644
index 0000000..bd70e70
--- /dev/null
+++ b/test/mjsunit/harmony/modules-skip-3-rqstd-order.mjs
@@ -0,0 +1,5 @@
+// Copyright 2019 the V8 project authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+Function('return this;')().test262.push('3');
diff --git a/test/mjsunit/harmony/modules-skip-3-top-level-await-cycle.mjs b/test/mjsunit/harmony/modules-skip-3-top-level-await-cycle.mjs
new file mode 100644
index 0000000..3171bb8
--- /dev/null
+++ b/test/mjsunit/harmony/modules-skip-3-top-level-await-cycle.mjs
@@ -0,0 +1,7 @@
+// Copyright 2019 the V8 project authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+import * as m from 'modules-skip-4-top-level-await-cycle.mjs';
+
+export { m };
diff --git a/test/mjsunit/harmony/modules-skip-3-top-level-await.mjs b/test/mjsunit/harmony/modules-skip-3-top-level-await.mjs
new file mode 100644
index 0000000..eea2c7a
--- /dev/null
+++ b/test/mjsunit/harmony/modules-skip-3-top-level-await.mjs
@@ -0,0 +1,12 @@
+// Copyright 2019 the V8 project authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+import * as m1 from 'modules-skip-1-top-level-await.mjs';
+import * as m2 from 'modules-skip-3.mjs';
+
+export function life() {
+  return m1.life();
+}
+
+export let stringlife = m2.stringlife;
diff --git a/test/mjsunit/harmony/modules-skip-4-rqstd-order-indirect-top-level-await.mjs b/test/mjsunit/harmony/modules-skip-4-rqstd-order-indirect-top-level-await.mjs
new file mode 100644
index 0000000..7c75a9a
--- /dev/null
+++ b/test/mjsunit/harmony/modules-skip-4-rqstd-order-indirect-top-level-await.mjs
@@ -0,0 +1,6 @@
+// Copyright 2019 the V8 project authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+import 'modules-skip-4-rqstd-order-top-level-await.mjs'
+Function('return this;')().test262.push('4_ind');
diff --git a/test/mjsunit/harmony/modules-skip-4-rqstd-order-top-level-await.mjs b/test/mjsunit/harmony/modules-skip-4-rqstd-order-top-level-await.mjs
new file mode 100644
index 0000000..1659ba6
--- /dev/null
+++ b/test/mjsunit/harmony/modules-skip-4-rqstd-order-top-level-await.mjs
@@ -0,0 +1,8 @@
+// Copyright 2019 the V8 project authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+Function('return this;')().test262.push('4_dir_a');
+let m = import('modules-skip-4-rqstd-order.mjs');
+await m;
+Function('return this;')().test262.push('4_dir_b');
diff --git a/test/mjsunit/harmony/modules-skip-4-rqstd-order.mjs b/test/mjsunit/harmony/modules-skip-4-rqstd-order.mjs
new file mode 100644
index 0000000..7fdd12c
--- /dev/null
+++ b/test/mjsunit/harmony/modules-skip-4-rqstd-order.mjs
@@ -0,0 +1,5 @@
+// Copyright 2019 the V8 project authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+Function('return this;')().test262.push('4');
diff --git a/test/mjsunit/harmony/modules-skip-4-top-level-await-cycle.mjs b/test/mjsunit/harmony/modules-skip-4-top-level-await-cycle.mjs
new file mode 100644
index 0000000..2b58e23
--- /dev/null
+++ b/test/mjsunit/harmony/modules-skip-4-top-level-await-cycle.mjs
@@ -0,0 +1,7 @@
+// Copyright 2019 the V8 project authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+let m = await import('modules-skip-1.mjs');
+
+export { m };
diff --git a/test/mjsunit/harmony/modules-skip-4-top-level-await.mjs b/test/mjsunit/harmony/modules-skip-4-top-level-await.mjs
new file mode 100644
index 0000000..00576a2
--- /dev/null
+++ b/test/mjsunit/harmony/modules-skip-4-top-level-await.mjs
@@ -0,0 +1,7 @@
+// Copyright 2019 the V8 project authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+import 'modules-skip-5-top-level-await.mjs';
+
+assertUnreachable();
diff --git a/test/mjsunit/harmony/modules-skip-5-top-level-await.mjs b/test/mjsunit/harmony/modules-skip-5-top-level-await.mjs
new file mode 100644
index 0000000..28cf2a9
--- /dev/null
+++ b/test/mjsunit/harmony/modules-skip-5-top-level-await.mjs
@@ -0,0 +1,5 @@
+// Copyright 2019 the V8 project authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+await import('modules-skip-2.mjs')
diff --git a/test/mjsunit/harmony/modules-skip-6-top-level-await.mjs b/test/mjsunit/harmony/modules-skip-6-top-level-await.mjs
new file mode 100644
index 0000000..65849db
--- /dev/null
+++ b/test/mjsunit/harmony/modules-skip-6-top-level-await.mjs
@@ -0,0 +1,10 @@
+// Copyright 2019 the V8 project authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+import * as m1 from 'modules-skip-3-top-level-await.mjs';
+
+let m2 = await import('modules-skip-1.mjs');
+
+export { m1, m2 };
+
diff --git a/test/mjsunit/harmony/modules-skip-7-top-level-await.mjs b/test/mjsunit/harmony/modules-skip-7-top-level-await.mjs
new file mode 100644
index 0000000..bc7f22b
--- /dev/null
+++ b/test/mjsunit/harmony/modules-skip-7-top-level-await.mjs
@@ -0,0 +1,14 @@
+// Copyright 2019 the V8 project authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+function sleeping_promise() {
+  return new Promise((resolve) => setTimeout(resolve));
+}
+
+export let life;
+
+await sleeping_promise();
+life = -1;
+await sleeping_promise();
+life = (await import('modules-skip-1.mjs')).life();
diff --git a/test/test262/testcfg.py b/test/test262/testcfg.py
index 691d38d..d4feca7 100644
--- a/test/test262/testcfg.py
+++ b/test/test262/testcfg.py
@@ -55,11 +55,11 @@
   'WeakRef': '--harmony-weak-refs',
   'host-gc-required': '--expose-gc-as=v8GC',
   'optional-chaining': '--harmony-optional-chaining',
+  'top-level-await': '--harmony-top-level-await',
 }
 
 SKIPPED_FEATURES = set(['class-methods-private',
-                        'class-static-methods-private',
-                        'top-level-await'])
+                        'class-static-methods-private'])
 
 DATA = os.path.join(os.path.dirname(os.path.abspath(__file__)), "data")