Skip to content
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

Late members declared with initializers are not initialized at optimization level 0 of dart2js #49599

Open
whesse opened this issue Aug 5, 2022 · 2 comments
Assignees
Labels
area-web Use area-web for Dart web related issues, including the DDC and dart2js compilers and JS interop. web-dart2js

Comments

@whesse
Copy link
Contributor

whesse commented Aug 5, 2022

A class with a late member, declared with an initializer, fails to get initialized when accessed if
the program is compiled with dart2js optimization level 0.

The initialization is carried out correctly at higher optimization levels.

The command

dart compile js -O0  test.dart -o test.dart.js

creates a compiled program that fails on Chrome, with the exception:

Uncaught TypeError: this.get$lateMap(...).putIfAbsent$2 is not a function
    at Foo.mapLookup$1 (test.dart:15:20)

on the program

void main()
{
  final foo = Foo();
  final bar = foo.mapLookup('a');
}

class Foo {
  late var lateMap = <String, String>{};
  var map = <String, String>{};

  String mapLookup(String key) {
    final result = map.putIfAbsent(key, () => 'b'); // Succeeds
    final getIt = lateMap; // Not needed to reproduce failure
    // print(getIt); // Fails - toString and runtimeType are absent.
    return lateMap.putIfAbsent(key, () =>'c'); // Fails
    
  }
}

The error is present on the stable branch, and on current tip-of-tree 2.19.0-59.0.dev.

@eernstg
Copy link
Member

eernstg commented Aug 5, 2022

Looking at the generated code, I find this:

    isSentinel(value) {
      return false;
    },

and that seems to make the logic around the late final variable go wrong: The variable lateFinalMap is considered initialized even though it isn't.

    get$lateFinalMap() {
      var t1, result,
        value = this.__Foo_lateFinalMap_FI;
      if (A.boolConversionCheck(A.isSentinel(value))) {
        t1 = type$.String;
        result = A.LinkedHashMap_LinkedHashMap$_empty(t1, t1);
        this.__Foo_lateFinalMap_FI !== $ && A.throwLateFieldADI("lateFinalMap");
        this.set$__Foo_lateFinalMap_FI(result);
        value = result;
      }
      return value;
    },

(Edit: I got the example from a different place, the variable was declared as late final lateFinalMap = <String, String>{}; in the example I compiled.)

@lrhn lrhn added the area-web Use area-web for Dart web related issues, including the DDC and dart2js compilers and JS interop. label Aug 5, 2022
@fishythefish
Copy link
Member

This is failing due to --disable-type-inference. See #48312 for a similar issue - I closed that one since some improvements we landed happened to fix it, but I can start digging into the root cause.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
area-web Use area-web for Dart web related issues, including the DDC and dart2js compilers and JS interop. web-dart2js
Projects
None yet
Development

No branches or pull requests

5 participants