Skip to content

Chaining generators produces wrong order of execution in ddc #53062

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

Open
yjbanov opened this issue Jul 27, 2023 · 0 comments
Open

Chaining generators produces wrong order of execution in ddc #53062

yjbanov opened this issue Jul 27, 2023 · 0 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 P2 A bug or feature request we're likely to work on web-dev-compiler

Comments

@yjbanov
Copy link

yjbanov commented Jul 27, 2023

Transfering flutter/flutter#131168 to the Dart SDK:

Steps to reproduce

Open dartpad, select Flutter, paste the code below. Then run and click the "Click" button.

For some reason goo proceeds past the yield before and it is asked to do so. Even replacing await showDialog with simple await Future.delayed(...) doesn't change the result.

It works correctly in pure Dart.

Expected results

foo START
goo START
Locked!
foo obj HERE
Unlocking...
Unlocked!
foo obj THERE
Creating operation...
foo obj HERE
Signing...
Signed!
foo obj THERE
Handling operation...
Handled!
goo END
foo END

Actual results

foo START
goo START
Locked!
foo obj HERE
Creating operation...
Unlocking...
foo obj THERE
foo obj HERE
Unlocked!
Signing...
Signed!
foo obj THERE
Handling operation...
Handled!
goo END
foo END

Code sample

Wrong order in Flutter
import 'package:flutter/material.dart';

const Color darkBlue = Color.fromARGB(255, 18, 32, 47);

void main() {
  runApp(MyApp());
}

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      theme: ThemeData.dark().copyWith(
        scaffoldBackgroundColor: darkBlue,
      ),
      debugShowCheckedModeBanner: false,
      home: Scaffold(
        body: Center(
          child: MyWidget(),
        ),
      ),
    );
  }
}

class MyWidget extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return TextButton(
      child: const Text('Click'),
      onPressed: () async {
        await for (var obj in foo()) {
          if (obj is LockedError) {
            print('Unlocking...');
            //await Future.delayed(const Duration(seconds: 1));
            await showDialog(
              context: context,
              builder: (_) => AlertDialog(
                title: const Text('Unlock'),
                actions: [
                  TextButton(
                    child: const Text('Ok'),
                    onPressed: () => Navigator.of(context).pop()
                  )
                ],
              ),
            );
            print('Unlocked!');
          } else if (obj is Operation) {
            print('Signing...');
            await showDialog(
              context: context,
              builder: (_) => AlertDialog(
                title: const Text('Sign operation'),
                actions: [
                  TextButton(
                    child: const Text('Ok'),
                    onPressed: () => Navigator.of(context).pop()
                  )
                ],
              ),
            );
            print('Signed!');
          }
        }
      }
    );
  }
}

Stream<Object> foo() async* {
  print('foo START');
  await for (var obj in goo()) {
    print('foo obj HERE');
    yield obj;
    print('foo obj THERE');
  }
  print('foo END');
}

Stream<Object> goo() async* {
  print('goo START');
  
  var locked = true;
  if (locked) {
    print('Locked!');
    yield LockedError();
  }
  
  print('Creating operation...');
  
  var op = Operation();
  yield op;
  
  print('Handling operation...');
  await Future.delayed(const Duration(seconds: 1));
  print('Handled!');
  
  print('goo END');
}

class LockedError {}

class Operation {}
Correct order in pure Dart
void main() async {
  await for (var obj in foo()) {
    if (obj is LockedError) {
      print('Unlocking...');
      await Future.delayed(const Duration(seconds: 1));
      print('Unlocked!');
    } else if (obj is Operation) {
      print('Signing...');
      await Future.delayed(const Duration(seconds: 1));
      print('Signed!');
    }
  }
}

Stream<Object> foo() async* {
  print('foo START');
  await for (var obj in goo()) {
    print('foo obj HERE');
    yield obj;
    print('foo obj THERE');
  }
  print('foo END');
}

Stream<Object> goo() async* {
  print('goo START');
  
  var locked = true;
  if (locked) {
    print('Locked!');
    yield LockedError();
  }
  
  print('Creating operation...');
  
  var op = Operation();
  yield op;
  
  print('Handling operation...');
  await Future.delayed(const Duration(seconds: 1));
  print('Handled!');
  
  print('goo END');
}

class LockedError {}

class Operation {}

Screenshots or Video

Screenshots / Video demonstration

[Upload media here]

Logs

Logs
[Paste your logs here]

Flutter Doctor output

Doctor output
Doctor summary (to see all details, run flutter doctor -v):
[√] Flutter (Channel stable, 3.10.2, on Microsoft Windows [Version 10.0.19045.3208], locale en-US)
[√] Windows Version (Installed version of Windows is version 10 or higher)
[√] Android toolchain - develop for Android devices (Android SDK version 30.0.1)
[√] Chrome - develop for the web
[√] Visual Studio - develop for Windows (Visual Studio Community 2019 16.11.9)  
[√] Android Studio (version 4.0)
[√] VS Code (version 1.80.1)
[√] Connected device (3 available)
[√] Network resources

• No issues found!
@lrhn lrhn added web-dev-compiler area-web-js Issues related to JavaScript support for Dart Web, including DDC, dart2js, and JS interop. labels Jul 27, 2023
@nshahan nshahan added dart2js-ddc-discrepancy When dev and production compilations have different semantics P2 A bug or feature request we're likely to work on labels Aug 18, 2023
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 P2 A bug or feature request we're likely to work on web-dev-compiler
Projects
None yet
Development

No branches or pull requests

4 participants