Skip to content

A catch block in an async* method does not catch exceptions from await for in DDC #47764

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
natebosch opened this issue Nov 24, 2021 · 7 comments
Labels
area-web-js Issues related to JavaScript support for Dart Web, including DDC, dart2js, and JS interop. dart2js-ddc-discrepancy When dev and production compilations have different semantics dev-compiler-async web-dev-compiler

Comments

@natebosch
Copy link
Member

Using a try/catch around an await for behaves differently on DDC from other platforms. In DDC the catch block is never reached and the stream never completes.

import 'dart:async';

void main() async {
  await doStuff(Stream.error('sad')).drain();
  print('Done');
}

Stream<String> doStuff(Stream<String> s) async* {
  try {
    await for (var e in s.handleError((e) {
      print('Stream error handler: $e');
      throw e;
    })) {
      yield e;
    }
  } catch (e) {
    print('Catch block: $e');
  }
}

In the VM and dart2js this outputs:

Stream error handler: sad
Catch block: sad
Done

In DDC this only outputs the first line.

@natebosch natebosch added web-dev-compiler area-web-js Issues related to JavaScript support for Dart Web, including DDC, dart2js, and JS interop. dart2js-ddc-discrepancy When dev and production compilations have different semantics labels Nov 24, 2021
@jakemac53
Copy link
Contributor

cc @sigmundch for triage

@nshahan
Copy link
Contributor

nshahan commented Dec 3, 2021

We are aware of issues where DDC's async implementation isn't correct. To help us prioritize the priority of fixing them can you give some context to how you discovered into this discrepancy? Was this triggered by a commonly use package or pattern from a framework?

@natebosch
Copy link
Member Author

This came up when a google3 author hit the problem. I have only seen it come up in real code the one time and it does not relate to a common pattern.

It's very confusing when it does come up.

@ricibald
Copy link

The issue is easily reproducible using the code in flutter/flutter#108866

@csells
Copy link

csells commented Nov 24, 2024

please note that "DDC" == "Dart Dev Compiler" aka the Dart compiler used in debug mode for the web.

also, for anyone interested, a work-around is to rewrite your code using yield* and map. For example, the following await for code:

try {
    final response = /* get a stream */;

    // works fine on every platform, including the web *except* on the web in the face of an exception in debug mode
    await for (final chunk in response) {
      final text = chunk.text;
      if (text != null) yield text;
    }
} on Exception catch(e) {
  // won't get here on the web in debug mode until this issue is fixed
}

can be rewritten like so:

try {
    final response = /* get a stream */;

    // seems to work fine on every platform, exception or not, debug mode or not
    yield* response
        .map((chunk) => chunk.text)
        .where((text) => text != null)
        .cast<String>();
} on Exception catch(e) {
  // handle the exception
}

It's not as pretty as that await for code, I admit, but it works.

@nshahan
Copy link
Contributor

nshahan commented Nov 26, 2024

@natebiggs Do you think we need to revisit the await for lowering now that we have new async logic?

@biggs0125
Copy link

This is fixed with the new DDC async semantics. Those updates included changes for await for. I've verified locally the code in the original comment now prints all 3 lines (same as dart2js and vm).

The updates to DDC's async semantics didn't make it into Dart 3.5 so they're not on the stable branch yet. They will be included with Dart 3.6 though. Changing DartPad to use the Beta channel instead of Stable also verifies that this will be fixed in 3.6.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
area-web-js Issues related to JavaScript support for Dart Web, including DDC, dart2js, and JS interop. dart2js-ddc-discrepancy When dev and production compilations have different semantics dev-compiler-async web-dev-compiler
Projects
None yet
Development

No branches or pull requests

7 participants