@@ -140,9 +140,9 @@ abstract class BindingBase {
140140 return true ;
141141 }());
142142
143- assert (! _debugInitialized );
143+ assert (_debugInitializedType == null );
144144 initInstances ();
145- assert (_debugInitialized );
145+ assert (_debugInitializedType != null );
146146
147147 assert (! _debugServiceExtensionsRegistered);
148148 initServiceExtensions ();
@@ -154,7 +154,7 @@ abstract class BindingBase {
154154 }
155155
156156 bool _debugConstructed = false ;
157- static bool _debugInitialized = false ;
157+ static Type ? _debugInitializedType ;
158158 static bool _debugServiceExtensionsRegistered = false ;
159159
160160 /// Additional configuration used by the framework during hot reload.
@@ -256,9 +256,9 @@ abstract class BindingBase {
256256 @protected
257257 @mustCallSuper
258258 void initInstances () {
259- assert (! _debugInitialized );
259+ assert (_debugInitializedType == null );
260260 assert (() {
261- _debugInitialized = true ;
261+ _debugInitializedType = runtimeType ;
262262 return true ;
263263 }());
264264 }
@@ -277,7 +277,7 @@ abstract class BindingBase {
277277 @protected
278278 static T checkInstance <T extends BindingBase >(T ? instance) {
279279 assert (() {
280- if (! _debugInitialized && instance == null ) {
280+ if (_debugInitializedType == null && instance == null ) {
281281 throw FlutterError .fromParts (< DiagnosticsNode > [
282282 ErrorSummary ('Binding has not yet been initialized.' ),
283283 ErrorDescription ('The "instance" getter on the $T binding mixin is only available once that binding has been initialized.' ),
@@ -298,7 +298,7 @@ abstract class BindingBase {
298298 ]);
299299 }
300300 if (instance == null ) {
301- assert (_debugInitialized );
301+ assert (_debugInitializedType == null );
302302 throw FlutterError .fromParts (< DiagnosticsNode > [
303303 ErrorSummary ('Binding mixin instance is null but bindings are already initialized.' ),
304304 ErrorDescription (
@@ -315,11 +315,14 @@ abstract class BindingBase {
315315 'It is also possible that $T does not implement "initInstances()" to assign a value to "instance". See the '
316316 'documentation of the BaseBinding class for more details.' ,
317317 ),
318+ ErrorHint (
319+ 'The binding that was initialized was of the type "$_debugInitializedType ". '
320+ ),
318321 ]);
319322 }
320323 try {
321324 assert (instance != null );
322- if (instance._debugConstructed && ! _debugInitialized ) {
325+ if (instance._debugConstructed && _debugInitializedType == null ) {
323326 throw FlutterError .fromParts (< DiagnosticsNode > [
324327 ErrorSummary ('Binding initialized without calling initInstances.' ),
325328 ErrorDescription ('An instance of $T is non-null, but BindingBase.initInstances() has not yet been called.' ),
@@ -335,7 +338,7 @@ abstract class BindingBase {
335338 ]);
336339 }
337340 if (! instance._debugConstructed) {
338- // The state of _debugInitialized doesn't matter in this failure mode.
341+ // The state of _debugInitializedType doesn't matter in this failure mode.
339342 throw FlutterError .fromParts (< DiagnosticsNode > [
340343 ErrorSummary ('Binding did not complete initialization.' ),
341344 ErrorDescription ('An instance of $T is non-null, but the BindingBase() constructor has not yet been called.' ),
@@ -361,6 +364,36 @@ abstract class BindingBase {
361364 return instance! ;
362365 }
363366
367+ /// In debug builds, the type of the current binding, if any, or else null.
368+ ///
369+ /// This may be useful in asserts to verify that the binding has not been initialized
370+ /// before the point in the application code that wants to initialize the binding, or
371+ /// to verify that the binding is the one that is expected.
372+ ///
373+ /// For example, if an application uses [Zone] s to report uncaught execptions, it may
374+ /// need to ensure that `ensureInitialized()` has not yet been invoked on any binding
375+ /// at the point where it configures the zone and initializes the binding.
376+ ///
377+ /// If this returns null, the binding has not been initialized.
378+ ///
379+ /// If this returns a non-null value, it returns the type of the binding instance.
380+ ///
381+ /// To obtain the binding itself, consider the `instance` getter on the [BindingBase]
382+ /// subclass or mixin.
383+ ///
384+ /// This method only returns a useful value in debug builds. In release builds, the
385+ /// return value is always null; to improve startup performance, the type of the
386+ /// binding is not tracked in release builds.
387+ ///
388+ /// See also:
389+ ///
390+ /// * [BindingBase] , whose class documentation describes the conventions for dealing
391+ /// with bindings.
392+ /// * [initInstances] , whose documentation details how to create a binding mixin.
393+ static Type ? debugBindingType () {
394+ return _debugInitializedType;
395+ }
396+
364397 /// Called when the binding is initialized, to register service
365398 /// extensions.
366399 ///
0 commit comments