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.07k stars 1.56k forks source link

dart2js: AsyncRewriter improvements #29532

Open rakudrama opened 7 years ago

rakudrama commented 7 years ago

The general purpose rewritten code has several shortcomings

Example:

    foo: function() {
      var $async$goto = 0, $async$completer = P.Completer_Completer$sync(), $async$returnValue, $async$handler = 2, $async$currentError;
      var $async$foo = P._wrapJsFunctionForAsync(function($async$errorCode, $async$result) {
        if ($async$errorCode === 1) {
          $async$currentError = $async$result;
          $async$goto = $async$handler;
        }
        while (true)
          switch ($async$goto) {
            case 0:
              // Function start
              $async$goto = 3;
              return P._asyncAwait(R.bar(), $async$foo);
            case 3:
              // returning from await.
              $async$returnValue = $async$result;
              // goto return
              $async$goto = 1;
              break;
            case 1:
              // return
              return P._asyncReturn($async$returnValue, $async$completer);
            case 2:
              // rethrow
              return P._asyncRethrow($async$currentError, $async$completer);
          }
      });
      return P._asyncStart($async$foo, $async$completer);
    },
    foo: function() {
      var $async$goto = 0, $async$completer = P.Completer_Completer$sync();
      var $async$foo = P._wrapJsFunctionForAsync(function($async$errorCode, $async$result) {
        if ($async$errorCode === 1)
          return P._asyncRethrow($async$result, $async$completer);
        switch ($async$goto) {
          case 0:
            // Function start
            $async$goto = 1;
            return P._asyncAwait(R.bar(), $async$foo);
          case 1:
            // returning from await.
            // return
            return P._asyncReturn($async$result, $async$completer);
        }
      });
      return P._asyncStart($async$foo, $async$completer);
    },
rakudrama commented 6 years ago

One thing to note is that the * variants, e.g. sync* can enter the state machine after it is finished. moveNext() continues to return false. This means that the transformed program should have a state that is 'stuck' at 'finished'. In the case of sync*, we could swizzle out the _body in _SyncStarIterator to a special 'stuck at finished' body to remove this constraint.