Web release mode build enum runtime type minification breaks existing Dart code

Description of Issue

A Web SKIA build that builds OK in debug mode fails to produce the same correct output in release mode!

Steps to Reproduce

This is a placeholder first stage of the issue report to register it. At the moment I can only provide output examples of the working debug mode build and failed release mode build, with warnings and errors they show in the Web console.

This issue occurs when we try to build our main project with Channel beta, 1.22.0-12.1.pre, but is also present when trying to build and release a new Web version of this tech demo https://rydmike.github.io/demoflexfold/#/ that contains many similar concepts so it is used as simpler demo below.

This tech demo app is also fairly complex, isolating what causes this issue to make a reproducible simpler sample might take a few days.

I verified that the same issue also occurs on latest master channel with Web SKIA release mode builds, did not test Dev channel yet.

This project requires SVG images, so it cannot be built with DomCanvas as some of the used drawing primitives are apparently not supported at all. In the failed example with the actual results, we can in the sidebar in the demo (animated GIF) see SVG files displayed in the SKIA release mode build, so the SVG files are working OK and are not the issue.

I also tried and verified that the used code with this issue, builds and runs fine on beta channel in release mode on Android devices without any warnings or issues, this is also the case on master channel when built in release mode for a device or even for Windows desktop.

Expected results

If we build the project in debug mode + SKIA:

flutter run -d chrome --debug --dart-define=FLUTTER_WEB_USE_SKIA=true --dart-define=FLUTTER_WEB_USE_EXPERIMENTAL_CANVAS_TEXT=true

It builds and runs OK, but with some warnings in the Web console:

WebBetaDebugSemiOK

The warnings are:

image

Actual results

If we build the project in release mode + SKIA:

flutter run -d chrome --release --dart-define=FLUTTER_WEB_USE_SKIA=true --dart-define=FLUTTER_WEB_USE_EXPERIMENTAL_CANVAS_TEXT=true

It builds OK, but it will not display any of the content in the applications body (which is using a nested navigator), there is just a grey box and some unexplained errors in the Web console.

WebBetaReleaseBroken

The errors it throws are:

image

Another exception was thrown: Instance of 'minified:fr<void>'
js_primitives.dart:47 Another exception was thrown: Instance of 'minified:fr<void>'
js_primitives.dart:47 Another exception was thrown: Instance of 'minified:fr<void>'
js_primitives.dart:47 Another exception was thrown: Instance of 'minified:fr<void>'
js_primitives.dart:47 Another exception was thrown: Instance of 'minified:fr<void>'
js_primitives.dart:47 Another exception was thrown: Instance of 'minified:fr<void>'
js_primitives.dart:47 Another exception was thrown: Instance of 'minified:fr<void>'
js_primitives.dart:47 Another exception was thrown: Instance of 'minified:fr<void>'
js_primitives.dart:47 Another exception was thrown: Instance of 'minified:fr<void>'
js_primitives.dart:47 Another exception was thrown: Instance of 'minified:fr<void>'
js_primitives.dart:47 Another exception was thrown: Instance of 'minified:fr<void>'
js_primitives.dart:47 Another exception was thrown: Instance of 'minified:fr<void>'
js_primitives.dart:47 Another exception was thrown: Instance of 'minified:fr<void>'
js_primitives.dart:47 Another exception was thrown: Instance of 'minified:fr<void>'
js_primitives.dart:47 Another exception was thrown: Instance of 'minified:fr<void>'
js_primitives.dart:47 Another exception was thrown: Instance of 'minified:fr<void>'
js_primitives.dart:47 Another exception was thrown: Instance of 'minified:fr<void>'
js_primitives.dart:47 Another exception was thrown: Instance of 'minified:fr<void>'
js_primitives.dart:47 Another exception was thrown: Instance of 'minified:fr<void>'
js_primitives.dart:47 Another exception was thrown: Instance of 'minified:fr<void>'
js_primitives.dart:47 Another exception was thrown: Instance of 'minified:fr<void>'
js_primitives.dart:47 Another exception was thrown: Instance of 'minified:fr<void>'
js_primitives.dart:47 Another exception was thrown: Instance of 'minified:fr<void>'
js_primitives.dart:47 Another exception was thrown: Instance of 'minified:fr<void>'
js_primitives.dart:47 Another exception was thrown: Instance of 'minified:fr<void>'
js_primitives.dart:47 Another exception was thrown: Instance of 'minified:fr<void>'
js_primitives.dart:47 Another exception was thrown: Instance of 'minified:fr<void>'
js_primitives.dart:47 Another exception was thrown: Instance of 'minified:fr<void>'
js_primitives.dart:47 Another exception was thrown: Instance of 'minified:fr<void>'

Flutter Doctor
>flutter doctor -v
[√] Flutter (Channel beta, 1.22.0-12.1.pre, on Microsoft Windows [Version 10.0.18363.1016], locale en-US)
    • Flutter version 1.22.0-12.1.pre at C:\Users\mryds\fvm\versions\beta
    • Framework revision 8b3760638a (5 days ago), 2020-09-15 17:47:13 -0700
    • Engine revision 4654fc6cf6
    • Dart version 2.10.0 (build 2.10.0-110.3.beta)

[√] Android toolchain - develop for Android devices (Android SDK version 29.0.1)
    • Android SDK at C:\Users\mryds\AppData\Local\Android\sdk
    • Platform android-29, build-tools 29.0.1
    • Java binary at: C:\Program Files\Android\Android Studio\jre\bin\java
    • Java version OpenJDK Runtime Environment (build 1.8.0_242-release-1644-b01)
    • All Android licenses accepted.

[√] Chrome - develop for the web
    • Chrome at C:\Program Files (x86)\Google\Chrome\Application\chrome.exe

[√] Android Studio (version 4.0)
    • Android Studio at C:\Program Files\Android\Android Studio
    • Flutter plugin version 49.0.2
    • Dart plugin version 193.7547
    • Java version OpenJDK Runtime Environment (build 1.8.0_242-release-1644-b01)

[√] IntelliJ IDEA Community Edition (version 2019.2)
    • IntelliJ at C:\Program Files\JetBrains\IntelliJ IDEA Community Edition 2018.3.1
    • Flutter plugin version 35.3.3
    • Dart plugin version 192.7402

[√] VS Code (version 1.49.1)
    • VS Code at C:\Users\mryds\AppData\Local\Programs\Microsoft VS Code
    • Flutter extension version 3.14.1

[√] Connected device (5 available)
    • Nexus 7 (mobile)                 • 0a99f5e8      • android-arm    • Android 6.0.1 (API 23)
    • sdk gphone x86 64 arm64 (mobile) • emulator-5554 • android-x64    • Android 11 (API 30) (emulator)
    • Web Server (web)                 • web-server    • web-javascript • Flutter Tools
    • Chrome (web)                     • chrome        • web-javascript • Google Chrome 85.0.4183.102
    • Edge (web)                       • edge          • web-javascript • Microsoft Edge 85.0.564.51

• No issues found!

2 thoughts on “Web release mode build enum runtime type minification breaks existing Dart code

  1. Issue update

    As mentioned above, I found the line that broke my Web release build in the example above and just eliminated the line that caused it and replaced it with something that worked.

    The code that broke the Web release build was in this pure Dart package: https://pub.dev/packages/enum_to_string because of line 19 in:

    https://github.com/rknell/flutterEnumsToString/blob/master/lib/enum_to_string.dart

    Where line 19 below

    15 class EnumToString {
    16   static bool _isEnumItem(enumItem) {
    17     final splitted_enum = enumItem.toString().split('.');
    18     return splitted_enum.length > 1 &&
    19         splitted_enum[0] == enumItem.runtimeType.toString();
    20  }

    will for correct API usage evaluate to false in a Web release build and true for all other Web build modes and all device or desktop mode builds as well.

    This difference then later in the package leads to that it throws an unhandled exception. For my particular usage that caused a crash in my Flutter build method that I could not observe on any other platform or build mode that would have been easier to debug.

    My solution was to replace the entire package with two lines of code, since I did not really need all the things it was doing anyway.

    The underlying cause, which is a dart2js runtime type minification issue, might be of general interest and may well have implications on existing Flutter and Dart code when using release mode Web builds.

    Below a simplified and reproducible sample.

    Step to reproduce

    A code sample for the root cause of the issue is available here:
    https://gist.github.com/rydmike/ba479df4c50457bcdadac6691bb0f84e

    It also contains the package code that lead to this discovery issue. The package code is not being used in the demo of the issue, but it can be used to show the use case and test how it breaks a build method in a Web release mode build, by uncommenting a simple Text() widget that will use it. When doing so, it also demonstrates why debugging and finding this issue the might be a bit tedious and tricky in a larger code base, the code just works OK and as expected and does produce any logs, errors or unexpected results, with any other target or build mode than Web –release mode.

    Expected result

    If we build and run the sample code for:

    • WEB with any current channel that supports Web builds, using DomCanvas or CanvasKit, with debug or profile mode.
    • Any device or desktop, in any build mode, with any Flutter version

    We get:

    image

    Actual result, with Web release mode on any channel at current versions

    If we build the same sample code in Web with any current Flutter channel that support Web builds, from beta, to dev and master using their latest versions, with DomCanvas or CanvasKit, but in release mode, we get:

    image

    We can see that the runtime type of the Enum has been minified to something that does not match its assumed enum runtime type.

    If some application code makes an assumption on this type and expect it to remain equal to how it is originally defined, then there is potential for breaking issues like the one that was observed in the case that lead to this discovery.

    In earlier Flutter beta versions (eg beta channel 1.21.0-9.2.pre) with the Dart SDK used then, this did not happen with Web --release mode builds, since the case that lead to this discovery used to build fine on it. Clearly something has changed in the release mode JS minification that caused this breaking change.

    Flutter Doctor
    
    flutter doctor -v
    [√] Flutter (Channel beta, 1.22.0-12.1.pre, on Microsoft Windows [Version 10.0.18363.1016], locale en-US)
        • Flutter version 1.22.0-12.1.pre at C:\Users\mryds\fvm\versions\beta
        • Framework revision 8b3760638a (7 days ago), 2020-09-15 17:47:13 -0700
        • Engine revision 4654fc6cf6
        • Dart version 2.10.0 (build 2.10.0-110.3.beta)
    
    [√] Android toolchain - develop for Android devices (Android SDK version 29.0.1)
        • Android SDK at C:\Users\mryds\AppData\Local\Android\sdk
        • Platform android-29, build-tools 29.0.1
        • Java binary at: C:\Program Files\Android\Android Studio\jre\bin\java
        • Java version OpenJDK Runtime Environment (build 1.8.0_242-release-1644-b01)
        • All Android licenses accepted.
    
    [√] Chrome - develop for the web
        • Chrome at C:\Program Files (x86)\Google\Chrome\Application\chrome.exe
    
    [√] Android Studio (version 4.0)
        • Android Studio at C:\Program Files\Android\Android Studio
        • Flutter plugin version 49.0.2
        • Dart plugin version 193.7547
        • Java version OpenJDK Runtime Environment (build 1.8.0_242-release-1644-b01)
    
    [√] IntelliJ IDEA Community Edition (version 2019.2)
        • IntelliJ at C:\Program Files\JetBrains\IntelliJ IDEA Community Edition 2018.3.1
        • Flutter plugin version 35.3.3
        • Dart plugin version 192.7402
    
    [√] VS Code (version 1.49.1)
        • VS Code at C:\Users\mryds\AppData\Local\Programs\Microsoft VS Code
        • Flutter extension version 3.14.1
    
    [√] Connected device (3 available)
        • Web Server (web) • web-server • web-javascript • Flutter Tools
        • Chrome (web)     • chrome     • web-javascript • Google Chrome 85.0.4183.121
        • Edge (web)       • edge       • web-javascript • Microsoft Edge 85.0.564.51
    
    • No issues found!
    
    

    cc: @yjbanov @TahaTesser and fyi: @mariamhas