Skip to content

Flutter web (only in release or profile) TypeError: Cannot read properties of null (reading 'pendingResult') #238

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
kosiarska opened this issue Dec 17, 2021 · 18 comments

Comments

@kosiarska
Copy link

kosiarska commented Dec 17, 2021

I can run the app in android studio with no problem, when i run
flutter run -d chrome --profile --dart-define=Dart2jsOptimization=O0
i get this error:

zrzut_ekranu_2021-12-17_o_17 50 14

@bohdan1krokhmaliuk
Copy link

Have similar issue, which blocks my project running in production/profile
image

@escamoteur
Copy link
Collaborator

can you create a simple repro project, please?

@HKop
Copy link

HKop commented Feb 2, 2022

@escamoteur Hi, I created a simple project that reproduces the same issue for me (HERE: https://github.com/HKop/getit-issue) It started happening once we extracted some of the files to a "lib_common" library and wanted to use them in the main app.

Project structure:

  1. getIt_issue main project.
  2. lib_common library in getIt_issue folder that has components used in the main project.

Note: Issue is only present on web in release or profile mode.

  1. To generate getIt files - "flutter packages pub run build_runner build --delete-conflicting-outputs" in the root getIt_issue folder;
  2. Then to run the app on web in profile mode - "flutter run --profile -d chrome --dart-define=Dart2jsOptimization=O0"

When opening the console, the following error is shown:

image

Otherwise, in debug mode, works properly and displays a button that calls a method from injected service:
image

P.S. The issue is not present also if the same classes are added to the main project (no lib_common present)

@escamoteur escamoteur added the web label Feb 4, 2022
@escamoteur
Copy link
Collaborator

This looks very much like a compiler bug

@escamoteur
Copy link
Collaborator

OK, after looking a bit deeper into your provided project it really looks pretty odd what dart2js produces here

_i1.GetIt $initGetIt(_i1.GetIt get,
    {String? environment, _i2.EnvironmentFilter? environmentFilter}) {
  final gh = _i2.GetItHelper(get, environment, environmentFilter);
  final libCommonModule = _$LibCommonModule(get);
  gh.factory<_i3.ISecureStorage>(() => libCommonModule.webSecureStorage,
      registerFor: {_web});
  gh.factory<_i3.ISecureStorage>(() => libCommonModule.mobileSecureStorage,
      registerFor: {_mobileOrDesktop});
  gh.lazySingleton<_i3.AppSecureStorage>(
      () => libCommonModule.appSecureStorage);
  gh.singleton<_i4.ObjectManager>(libCommonModule.objectManager);
  return get;
}

this is the dart code where it happens

the JS code for this part looks like

    $initGetIt(get, environment) {
      var t3, _null = null,
        gh = A.GetItHelper$(get, environment, _null),
        libCommonModule = new A._$LibCommonModule(get),
        t1 = type$.String,
        t2 = type$.ISecureStorage;
      gh.factory$1$2$registerFor(new A.$initGetIt_closure(libCommonModule), A.LinkedHashSet_LinkedHashSet$_literal(["web"], t1), t2);
      gh.factory$1$2$registerFor(new A.$initGetIt_closure0(libCommonModule), A.LinkedHashSet_LinkedHashSet$_literal(["mobileOrDesktop"], t1), t2);
      if (gh._canRegister$1(_null))
        gh.getIt.registerLazySingleton$1$3$dispose$instanceName(new A.$initGetIt_closure1(libCommonModule), _null, _null, type$.AppSecureStorage);
      t1 = get.call$0();
      if (gh._canRegister$1(_null)) {
        t2 = A._setArrayType([], type$.JSArray_ObjectManager);
        t3 = type$.void;
        gh.getIt._register$3$6$disposeFunc$instance$instanceName$isAsync$shouldSignalReady$type(_null, new A.ObjectManager(t1), _null, false, type$.List_WillSignalReady._is(t2), B._ServiceFactoryType_1, type$.ObjectManager, t3, t3);
      }
      return get;
    },

I have no idea were this line comes from

  t1 = get.call$0();

also, the variable t1 isn't used anymore inside this function.

Looking at the code of call$0 it gets even weirder

    call$1$0($T) {
      var instance, _null = null,
        instanceFactory = this._findFirstFactoryByNameAndTypeOrNull$1$2$type(_null, _null, $T),
        t1 = instanceFactory.pendingResult;
      if (t1 != null) {
        t1 = instanceFactory.instance;
        t1.toString;
        instance = t1;
      } else
        instance = instanceFactory.getObject$2(0, _null, _null);
      return $T._as(instance);
    },
    call$0() {
      return this.call$1$0(type$.Object);
    },

and I have no idea which part of my get_it package this should come from? My only hunch is could that be created from an assert because the toString() is really weird especially as the result isn't assigned to anything.

@kevmoo @leafpetersen

Several of my users are affected by this.

@escamoteur escamoteur changed the title Flutter web TypeError: Cannot read properties of null (reading 'pendingResult') Flutter web (only in release or profile) TypeError: Cannot read properties of null (reading 'pendingResult') Feb 4, 2022
@kevmoo
Copy link

kevmoo commented Feb 4, 2022

Flagging our web team on this now!

@escamoteur
Copy link
Collaborator

Thanks a lot

@sigmundch
Copy link

I'll follow up in more detail in the dart-sdk bug, but wanted to mention a couple things I noticed in my investigation:

  • the .pendingResult or .toString are signal of a null-check failing
  • the t1 = call$0() comes from inlining other code. In this case it is from the call method in the GetItImplementation class. Which is invoked from this piece of generated code:
  _i4.ObjectManager get objectManager =>
      _i4.ObjectManager(_getIt<_i3.AppSecureStorage>());
  • it's quite likely that dart2js has a bug related to call methods. If I change the generated code by hand to use _getIt.get<i3.AppSecureStorage>(), then the code works for me locally.

Note that my experiments are with a trimmed-down version of the app, I haven't validated that this works again with the full application.

@escamoteur
Copy link
Collaborator

escamoteur commented Feb 4, 2022 via email

@JHBitencourt
Copy link
Contributor

JHBitencourt commented Feb 17, 2022

Any news on this? atm I can't compile my project to web. Maybe a temp fix?

Same error
Uncaught TypeError: Cannot read properties of null (reading 'toString')
  at html_dart2js.dart:40810:45
  at a6c.a (async_patch.dart:316:19)
  at a6c.$2 (async_patch.dart:341:23)
  at Object.ab (async_patch.dart:246:3)
  at a6N (main.dart:10:27)
  at js_helper.dart:2684:31
  at js_helper.dart:2684:31
  at dartProgram (js_helper.dart:2684:31)
  at js_helper.dart:2684:31

@sigmundch
Copy link

Regarding the original issue here, note that we've continued the dart level discussion at dart-lang/sdk#48304 - the specific issue with the get_it package relates to using callable objects via the call method.

@JHBitencourt - your error could potentially be caused by something else. toString is the way dart2js represents null checks when emitting JavaScript, so this could be any kind of null check in a program. Usually those can be detected when running the application in debug mode. If not, I'd recommend trying first to isolate the issue in profile mode (where dart2js generates almost identical code to release mode but disables name minification).

@JHBitencourt
Copy link
Contributor

JHBitencourt commented Feb 17, 2022

@sigmundch thanks for replying. When in debug everything works perfect. Both profile and release mode produce the same output. I came here because at a6N (main.dart:10:27) points to where I'm making a get_it call. I'll investigate further though.

@HKop
Copy link

HKop commented Feb 18, 2022

Any news on this? atm I can't compile my project to web. Maybe a temp fix?

Same error

Here (https://github.com/HKop/getit-issue) on another branch (called no-injectable) I managed to make it work, but it's not an ideal solution - in my case I tried registering dependencies manually in the lib_common package (without @Injectable annotations). I still used @Injectable in the main app with no problems. This resolved the issue for me, though I'd much prefer to use annotations with getIt instead of registering them manually.

@Spiderbezno
Copy link

There ara a related problem with flutter web, if you use getIt.registerSingleton(AppModelImplementation()); the error is NoSuchMethodError: method not found: 'pendingResult' on null
but if use getIt.registerLazySingleton(() => RestAPIImplementation()); the error is NoSuchMethodError: method not found: 'db' on null

@kosiarska
Copy link
Author

As a temporary solution i solved it by removing arguments from constructors of injected classes and I assigned every field with getIt().value

@escamoteur
Copy link
Collaborator

does this problem still exist? because a fix was added into the dart2js if I read the above link correctly?

@sigmundch
Copy link

To clarify - the fix landed in the Dart sdk and is part of the Dart 2.17 beta at the moment, it should be part of the 2.17 stable once that gets released. If flutter beta is in sync with Dart beta releases (which I believe it is), then I'd expect this to be resolved in both the master and beta flutter channels at the moment, but not on the stable channel.

@escamoteur
Copy link
Collaborator

can anyone confirm, that this is now solved?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

8 participants