[ddc] Reconciling d8 and Chrome timing differences in hot reload suite.

Appending a script to the DOM in Chrome causes microtasks to fire. This change makes the `hotRestart` pathway async and inserts an async callback at the hot restart boundary for d8.

Change-Id: Ib05e9e496b6313d861fb5cb691a5894beed62a6e
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/389224
Reviewed-by: Nicholas Shahan <nshahan@google.com>
diff --git a/pkg/dev_compiler/lib/js/ddc/ddc_module_loader.js b/pkg/dev_compiler/lib/js/ddc/ddc_module_loader.js
index 564199f..5646c10 100644
--- a/pkg/dev_compiler/lib/js/ddc/ddc_module_loader.js
+++ b/pkg/dev_compiler/lib/js/ddc/ddc_module_loader.js
@@ -1701,8 +1701,8 @@
      * Immediately triggers a hot restart of the application losing all state
      * and running the main method again.
      */
-    hotRestart() {
-      self.$dartReloadModifiedModules(
+    async hotRestart() {
+      await self.$dartReloadModifiedModules(
         libraryManager.savedEntryPointLibraryName,
         () => { libraryManager.hotRestart(); });
     }
diff --git a/pkg/reload_test/lib/ddc_helpers.dart b/pkg/reload_test/lib/ddc_helpers.dart
index e06b20a..e4a197d 100644
--- a/pkg/reload_test/lib/ddc_helpers.dart
+++ b/pkg/reload_test/lib/ddc_helpers.dart
@@ -124,7 +124,7 @@
 let previousGenerations = new Set();
 
 // Append a helper function for hot restart.
-self.\$dartReloadModifiedModules = function(subAppName, callback) {
+self.\$dartReloadModifiedModules = async function(subAppName, callback) {
   let expectedName = "$entrypointModuleName";
   if (subAppName !== expectedName) {
     throw Error("Unexpected app name " + subAppName
@@ -152,8 +152,9 @@
     self.\$dartLoader.forceLoadScript(modifiedFilePath);
   }
 
-  // Run main.
-  callback();
+  // Run main in an async callback. D8 performs synchronous loads, so we need
+  // to insert an async task to match its semantics to that of Chrome.
+  await Promise.resolve().then(() => { callback(); });
 }
 
 // Append a helper function for hot reload.
@@ -467,7 +468,7 @@
       return [fileUrls, libraryIds];
     }
 
-    self.\$dartReloadModifiedModules = function(subAppName, callback) {
+    self.\$dartReloadModifiedModules = async function(subAppName, callback) {
       let expectedName = "$entrypointModuleName";
       if (subAppName !== expectedName) {
         throw Error("Unexpected app name " + subAppName
diff --git a/pkg/reload_test/lib/src/_ddc_reload_utils.dart b/pkg/reload_test/lib/src/_ddc_reload_utils.dart
index 6c0f2ee..b2c8bcf 100644
--- a/pkg/reload_test/lib/src/_ddc_reload_utils.dart
+++ b/pkg/reload_test/lib/src/_ddc_reload_utils.dart
@@ -23,7 +23,7 @@
 
 extension type _DartDevEmbedder(JSObject _) implements JSObject {
   external JSFunction hotReload;
-  external void hotRestart();
+  external JSFunction hotRestart;
   external JSNumber get hotReloadGeneration;
   external JSNumber get hotRestartGeneration;
 }
@@ -41,9 +41,9 @@
 
 int get hotRestartGeneration => _dartDevEmbedder.hotRestartGeneration.toDartInt;
 
-void hotRestart() {
+Future<void> hotRestart() async {
   _ddcLoader.intendedHotRestartGeneration++;
-  _dartDevEmbedder.hotRestart();
+  await (_dartDevEmbedder.hotRestart.callAsFunction() as JSPromise).toDart;
 }
 
 int get hotReloadGeneration => _dartDevEmbedder.hotReloadGeneration.toDartInt;
diff --git a/pkg/reload_test/lib/src/_reload_utils_api.dart b/pkg/reload_test/lib/src/_reload_utils_api.dart
index c97b08f..d0d7d29 100644
--- a/pkg/reload_test/lib/src/_reload_utils_api.dart
+++ b/pkg/reload_test/lib/src/_reload_utils_api.dart
@@ -7,10 +7,11 @@
 int get hotRestartGeneration =>
     throw Exception('Not implemented on this platform.');
 
-void hotRestart() => throw Exception('Not implemented on this platform.');
+Future<void> hotRestart() async =>
+    throw Exception('Not implemented on this platform.');
 
 int get hotReloadGeneration =>
     throw Exception('Not implemented on this platform.');
 
-Future<void> hotReload() =>
+Future<void> hotReload() async =>
     throw Exception('Not implemented on this platform.');
diff --git a/pkg/reload_test/lib/src/_vm_reload_utils.dart b/pkg/reload_test/lib/src/_vm_reload_utils.dart
index 70d362e..a0f4b6c 100644
--- a/pkg/reload_test/lib/src/_vm_reload_utils.dart
+++ b/pkg/reload_test/lib/src/_vm_reload_utils.dart
@@ -12,7 +12,8 @@
 int get hotRestartGeneration =>
     throw Exception('Not implemented on this platform.');
 
-void hotRestart() => throw Exception('Not implemented on this platform.');
+Future<void> hotRestart() async =>
+    throw Exception('Not implemented on this platform.');
 
 int _reloadCounter = 0;
 int get hotReloadGeneration => _reloadCounter;
diff --git a/tests/hot_reload/framework_timing_test/main.0.dart b/tests/hot_reload/framework_timing_test/main.0.dart
index 3d3bdab..440f6f3 100644
--- a/tests/hot_reload/framework_timing_test/main.0.dart
+++ b/tests/hot_reload/framework_timing_test/main.0.dart
@@ -9,7 +9,7 @@
 
 var x = 'Hello World';
 
-void main() {
+Future<void> main() async {
   Expect.equals('Hello World', x);
   Expect.equals(0, hotRestartGeneration);
 
@@ -29,5 +29,5 @@
         'This should never run.');
   });
 
-  hotRestart();
+  await hotRestart();
 }
diff --git a/tests/hot_reload/framework_timing_test/main.1.dart b/tests/hot_reload/framework_timing_test/main.1.dart
index d3be3e1..03a7706 100644
--- a/tests/hot_reload/framework_timing_test/main.1.dart
+++ b/tests/hot_reload/framework_timing_test/main.1.dart
@@ -9,7 +9,7 @@
 
 var x = 'Hello Foo';
 
-void main() {
+Future<void> main() async {
   Expect.equals('Hello Foo', x);
   Expect.equals(1, hotRestartGeneration);
 
@@ -29,7 +29,7 @@
         'This should never run.');
   });
 
-  hotRestart();
+  await hotRestart();
 }
 /** DIFF **/
 /*
@@ -40,7 +40,7 @@
 -var x = 'Hello World';
 +var x = 'Hello Foo';
  
- void main() {
+ Future<void> main() async {
 -  Expect.equals('Hello World', x);
 -  Expect.equals(0, hotRestartGeneration);
 +  Expect.equals('Hello Foo', x);
diff --git a/tests/hot_reload/framework_timing_test/main.2.dart b/tests/hot_reload/framework_timing_test/main.2.dart
index dc81e6a..20ae638 100644
--- a/tests/hot_reload/framework_timing_test/main.2.dart
+++ b/tests/hot_reload/framework_timing_test/main.2.dart
@@ -9,7 +9,7 @@
 
 var x = 'Hello Bar';
 
-void main() {
+Future<void> main() async {
   Expect.equals('Hello Bar', x);
   Expect.equals(2, hotRestartGeneration);
 
@@ -24,7 +24,7 @@
   }).then((_) {
     Expect.equals(2, hotRestartGeneration);
   });
-  hotRestart();
+  await hotRestart();
 }
 /** DIFF **/
 /*
@@ -35,7 +35,7 @@
 -var x = 'Hello Foo';
 +var x = 'Hello Bar';
  
- void main() {
+ Future<void> main() async {
 -  Expect.equals('Hello Foo', x);
 -  Expect.equals(1, hotRestartGeneration);
 +  Expect.equals('Hello Bar', x);
@@ -61,6 +61,6 @@
 -        'This should never run.');
 -  });
 -
-   hotRestart();
+   await hotRestart();
  }
 */
diff --git a/tests/hot_reload/hot_restart_constant_equality/main.0.dart b/tests/hot_reload/hot_restart_constant_equality/main.0.dart
index 7350e1d..d95beab 100644
--- a/tests/hot_reload/hot_restart_constant_equality/main.0.dart
+++ b/tests/hot_reload/hot_restart_constant_equality/main.0.dart
@@ -27,8 +27,8 @@
       '${value1 == value2 ? 'ConstantEqualitySuccess' : 'ConstantEqualityFailure'})';
 }
 
-void main() {
+Future<void> main() async {
   Expect.equals('ConstObject(reloadVariable: 23, ConstantEqualitySuccess)',
       '${const ConstObject().text}');
-  hotRestart();
+  await hotRestart();
 }
diff --git a/tests/hot_reload/hot_restart_constant_equality/main.1.dart b/tests/hot_reload/hot_restart_constant_equality/main.1.dart
index b22ed53..8fe21c1 100644
--- a/tests/hot_reload/hot_restart_constant_equality/main.1.dart
+++ b/tests/hot_reload/hot_restart_constant_equality/main.1.dart
@@ -27,7 +27,7 @@
       '${value1 == value2 ? 'ConstantEqualitySuccess' : 'ConstantEqualityFailure'})';
 }
 
-void main() {
+Future<void> main() async {
   Expect.equals('ConstObject(reloadVariable: 45, ConstantEqualitySuccess)',
       '${const ConstObject().text}');
 }
@@ -36,10 +36,10 @@
 @@ -28,7 +28,6 @@
  }
  
- void main() {
+ Future<void> main() async {
 -  Expect.equals('ConstObject(reloadVariable: 23, ConstantEqualitySuccess)',
 +  Expect.equals('ConstObject(reloadVariable: 45, ConstantEqualitySuccess)',
        '${const ConstObject().text}');
--  hotRestart();
+-  await hotRestart();
  }
 */