dart-lang / sdk

The Dart SDK, including the VM, JS and Wasm compilers, analysis, core libraries, and more.
https://dart.dev
BSD 3-Clause "New" or "Revised" License
10.04k stars 1.55k forks source link

dart2js error #38474

Open baonhan opened 4 years ago

baonhan commented 4 years ago

dart2js version: 2.6.0-2019-09-18 OS: Linux Browser: Chrome

dart2js compiles the following dart code to wrong js.

var t = 0;

Future<String> test() async {
  var r = 'test1';
  if (t  == 1) {
    var result = await test2();
    switch(result) {
      case 'test2':
        r = 'test2';
        break;
    }
  }
  return r;
}

Future<String> test2() async {
  return 'test2';
}

main() async {
  t = 1;
  print(await test());
}

Output when running in Dart VM: test2 Output when running js in Chrome: null

Compiled js file: test.dart.js.txt

sigmundch commented 4 years ago

Thank you for the filed request and for the great small example to reproduce the issue.

Here is the relevant part of the output:

    test: function() {
      var $async$goto = 0,
        $async$completer = P._makeAsyncAwaitCompleter(P.String),
        $async$returnValue, r;
      var $async$test = P._wrapJsFunctionForAsync(function($async$errorCode, $async$result) {
        if ($async$errorCode === 1)
          return P._asyncRethrow($async$result, $async$completer);
        while (true)
          switch ($async$goto) {
            case 0:
              // Function start
              if ($.t === 1) {
                $async$goto = 3;
                return P._asyncAwait(Y.test2(), $async$test);
              } else
                r = "test";
              $async$returnValue = r;
              // goto return
              $async$goto = 1;
              break;
            case 3:
              // returning from await.
              switch ($async$result) {
                case "test2":
                  r = "test2";
                  break a;
                default:
                  r = "test";
              }
            case 1:
              // return
              return P._asyncReturn($async$returnValue, $async$completer);
          }
        console.log("out of loop");
      });
      return P._asyncStartSync($async$test, $async$completer);
    },

It appears that we don't set the $async$returnValue in case 3!

edit: I was twiddling with the strings, just updated the text to match the original repro.