Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Submit feedback
Sign in
Toggle navigation
F
Front-End
Project
Project
Details
Activity
Releases
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
abdullh.alsoleman
Front-End
Commits
6fabdd04
Unverified
Commit
6fabdd04
authored
Sep 22, 2021
by
nt4f04uNd
Committed by
GitHub
Sep 22, 2021
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Make structuredErrors to not mess up with onError (#88253)
parent
fb0cbb8b
Changes
4
Hide whitespace changes
Inline
Side-by-side
Showing
4 changed files
with
67 additions
and
132 deletions
+67
-132
assertions.dart
packages/flutter/lib/src/foundation/assertions.dart
+8
-1
widget_inspector.dart
packages/flutter/lib/src/widgets/widget_inspector.dart
+6
-9
widget_inspector_init_with_structured_error_test.dart
...ets/widget_inspector_init_with_structured_error_test.dart
+0
-61
widget_inspector_structure_error_test.dart
...r/test/widgets/widget_inspector_structure_error_test.dart
+53
-61
No files found.
packages/flutter/lib/src/foundation/assertions.dart
View file @
6fabdd04
...
...
@@ -867,7 +867,9 @@ class FlutterError extends Error with DiagnosticableTreeMixin implements Asserti
/// The default behavior is to call [presentError].
///
/// You can set this to your own function to override this default behavior.
/// For example, you could report all errors to your server.
/// For example, you could report all errors to your server. Consider calling
/// [presentError] from your custom error handler in order to see the logs in
/// the console as well.
///
/// If the error handler throws an exception, it will not be caught by the
/// Flutter framework.
...
...
@@ -877,6 +879,11 @@ class FlutterError extends Error with DiagnosticableTreeMixin implements Asserti
///
/// Do not call [onError] directly, instead, call [reportError], which
/// forwards to [onError] if it is not null.
///
/// See also:
///
/// * <https://flutter.dev/docs/testing/errors>, more information about error
/// handling in Flutter.
static
FlutterExceptionHandler
?
onError
=
presentError
;
/// Called by the Flutter framework before attempting to parse a [StackTrace].
...
...
packages/flutter/lib/src/widgets/widget_inspector.dart
View file @
6fabdd04
...
...
@@ -746,8 +746,6 @@ mixin WidgetInspectorService {
bool
_trackRebuildDirtyWidgets
=
false
;
bool
_trackRepaintWidgets
=
false
;
FlutterExceptionHandler
?
_structuredExceptionHandler
;
late
RegisterServiceExtensionCallback
_registerServiceExtensionCallback
;
/// Registers a service extension method with the given name (full
/// name "ext.flutter.inspector.name").
...
...
@@ -920,7 +918,7 @@ mixin WidgetInspectorService {
int
_errorsSinceReload
=
0
;
void
_reportError
(
FlutterErrorDetails
details
)
{
void
_report
Structured
Error
(
FlutterErrorDetails
details
)
{
final
Map
<
String
,
Object
?>
errorJson
=
_nodeToJson
(
details
.
toDiagnosticsNode
(),
InspectorSerializationDelegate
(
...
...
@@ -981,9 +979,10 @@ mixin WidgetInspectorService {
/// * [BindingBase.initServiceExtensions], which explains when service
/// extensions can be used.
void
initServiceExtensions
(
RegisterServiceExtensionCallback
registerServiceExtensionCallback
)
{
_structuredExceptionHandler
=
_reportError
;
final
FlutterExceptionHandler
defaultExceptionHandler
=
FlutterError
.
presentError
;
if
(
isStructuredErrorsEnabled
())
{
FlutterError
.
onError
=
_structuredExceptionHandle
r
;
FlutterError
.
presentError
=
_reportStructuredErro
r
;
}
_registerServiceExtensionCallback
=
registerServiceExtensionCallback
;
assert
(!
_debugServiceExtensionsRegistered
);
...
...
@@ -994,13 +993,11 @@ mixin WidgetInspectorService {
SchedulerBinding
.
instance
!.
addPersistentFrameCallback
(
_onFrameStart
);
final
FlutterExceptionHandler
defaultExceptionHandler
=
FlutterError
.
presentError
;
_registerBoolServiceExtension
(
name:
'structuredErrors'
,
getter:
()
async
=>
FlutterError
.
presentError
==
_
structuredExceptionHandle
r
,
getter:
()
async
=>
FlutterError
.
presentError
==
_
reportStructuredErro
r
,
setter:
(
bool
value
)
{
FlutterError
.
presentError
=
value
?
_
structuredExceptionHandler
!
:
defaultExceptionHandler
;
FlutterError
.
presentError
=
value
?
_
reportStructuredError
:
defaultExceptionHandler
;
return
Future
<
void
>.
value
();
},
);
...
...
packages/flutter/test/widgets/widget_inspector_init_with_structured_error_test.dart
deleted
100644 → 0
View file @
fb0cbb8b
// Copyright 2014 The Flutter Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
import
'package:flutter/foundation.dart'
;
import
'package:flutter/material.dart'
;
import
'package:flutter/widgets.dart'
;
import
'package:flutter_test/flutter_test.dart'
;
import
'widget_inspector_test_utils.dart'
;
void
main
(
)
{
StructuredErrorTestService
.
runTests
();
}
class
StructuredErrorTestService
extends
TestWidgetInspectorService
{
@override
bool
isStructuredErrorsEnabled
()
{
return
true
;
}
static
void
runTests
()
{
final
StructuredErrorTestService
service
=
StructuredErrorTestService
();
WidgetInspectorService
.
instance
=
service
;
FlutterExceptionHandler
?
testHandler
;
FlutterExceptionHandler
?
inspectorServiceErrorHandler
;
setUpAll
(()
{
inspectorServiceErrorHandler
=
FlutterError
.
onError
;
});
setUp
(()
{
testHandler
=
FlutterError
.
onError
;
});
testWidgets
(
'ext.flutter.inspector.setStructuredErrors'
,
(
WidgetTester
tester
)
async
{
// The test framework resets FlutterError.onError, so we set it back to
// what it was after WidgetInspectorService::initServiceExtensions ran.
FlutterError
.
onError
=
inspectorServiceErrorHandler
;
List
<
Map
<
Object
,
Object
?>>
flutterErrorEvents
=
service
.
getEventsDispatched
(
'Flutter.Error'
);
expect
(
flutterErrorEvents
,
hasLength
(
0
));
// Create an error.
FlutterError
.
reportError
(
FlutterErrorDetails
(
library
:
'rendering library'
,
context:
ErrorDescription
(
'during layout'
),
exception:
StackTrace
.
current
,
));
// Validate that we received an error.
flutterErrorEvents
=
service
.
getEventsDispatched
(
'Flutter.Error'
);
expect
(
flutterErrorEvents
,
hasLength
(
1
));
});
tearDown
(()
{
FlutterError
.
onError
=
testHandler
;
});
}
}
packages/flutter/test/widgets/widget_inspector_structure_error_test.dart
View file @
6fabdd04
...
...
@@ -2,93 +2,85 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
import
'dart:async'
;
import
'dart:convert'
;
import
'package:flutter/foundation.dart'
;
import
'package:flutter/widgets.dart'
;
import
'package:flutter_test/flutter_test.dart'
;
import
'widget_inspector_test_utils.dart'
;
void
main
(
)
{
StructureErrorTestWidgetInspectorService
.
runTests
();
}
typedef
InspectorServiceExtensionCallback
=
FutureOr
<
Map
<
String
,
Object
?>>
Function
(
Map
<
String
,
String
>
parameters
);
class
StructureErrorTestWidgetInspectorService
extends
TestWidgetInspectorService
{
static
void
runTests
()
{
final
StructureErrorTestWidgetInspectorService
service
=
StructureErrorTestWidgetInspectorService
();
WidgetInspectorService
.
instance
=
service
;
class
StructureErrorTestWidgetInspectorService
extends
Object
with
WidgetInspectorService
{
final
Map
<
String
,
InspectorServiceExtensionCallback
>
extensions
=
<
String
,
InspectorServiceExtensionCallback
>{};
test
(
'ext.flutter.inspector.structuredErrors - custom FlutterError.onError'
,
()
async
{
// Regression test for https://github.com/flutter/flutter/issues/41540
final
Map
<
String
,
List
<
Map
<
Object
,
Object
?>>>
eventsDispatched
=
<
String
,
List
<
Map
<
Object
,
Object
?>>>{};
// Ensures that
// * structured errors are enabled by default
// * FlutterError.onError without FlutterError.presentError doesn't present structured errors
// * FlutterError.onError with FlutterError.presentError does present structured errors
// * disabling structured errors sets the default FlutterError.presentError
@override
void
registerServiceExtension
({
required
String
name
,
required
FutureOr
<
Map
<
String
,
Object
?>>
Function
(
Map
<
String
,
String
>
parameters
)
callback
,
})
{
assert
(!
extensions
.
containsKey
(
name
));
extensions
[
name
]
=
callback
;
}
final
FlutterExceptionHandler
?
oldHandler
=
FlutterError
.
onError
;
@override
void
postEvent
(
String
eventKind
,
Map
<
Object
,
Object
?>
eventData
)
{
getEventsDispatched
(
eventKind
).
add
(
eventData
);
}
try
{
expect
(
service
.
getEventsDispatched
(
'Flutter.Error'
),
isEmpty
);
List
<
Map
<
Object
,
Object
?>>
getEventsDispatched
(
String
eventKind
)
{
return
eventsDispatched
.
putIfAbsent
(
eventKind
,
()
=>
<
Map
<
Object
,
Object
?>>[]);
}
// Set callback that doesn't call presentError.
bool
onErrorCalled
=
false
;
FlutterError
.
onError
=
(
FlutterErrorDetails
details
)
{
onErrorCalled
=
true
;
};
Iterable
<
Map
<
Object
,
Object
?>>
getServiceExtensionStateChangedEvents
(
String
extensionName
)
{
return
getEventsDispatched
(
'Flutter.ServiceExtensionStateChanged'
)
.
where
((
Map
<
Object
,
Object
?>
event
)
=>
event
[
'extension'
]
==
extensionName
);
}
// Get the service registered.
WidgetsFlutterBinding
.
ensureInitialized
();
Future
<
String
>
testBoolExtension
(
String
name
,
Map
<
String
,
String
>
arguments
)
async
{
expect
(
extensions
,
contains
(
name
));
// Encode and decode to JSON to match behavior using a real service
// extension where only JSON is allowed.
// ignore: avoid_dynamic_calls
return
json
.
decode
(
json
.
encode
(
await
extensions
[
name
]!(
arguments
)))[
'enabled'
]
as
String
;
}
final
FlutterErrorDetails
expectedError
=
FlutterErrorDetails
(
library
:
'rendering library'
,
context:
ErrorDescription
(
'during layout'
),
exception:
StackTrace
.
current
,
);
FlutterError
.
reportError
(
expectedError
);
// Verify structured errors are not shown.
expect
(
onErrorCalled
,
true
);
expect
(
service
.
getEventsDispatched
(
'Flutter.Error'
),
isEmpty
);
static
void
runTests
()
{
final
StructureErrorTestWidgetInspectorService
service
=
StructureErrorTestWidgetInspectorService
();
WidgetInspectorService
.
instance
=
service
;
// Set callback that calls presentError.
onErrorCalled
=
false
;
FlutterError
.
onError
=
(
FlutterErrorDetails
details
)
{
FlutterError
.
presentError
(
details
);
onErrorCalled
=
true
;
};
test
(
'ext.flutter.inspector.structuredErrors reports error to _structuredExceptionHandler on error'
,
()
async
{
final
FlutterExceptionHandler
?
oldHandler
=
FlutterError
.
onError
;
FlutterError
.
reportError
(
expectedError
);
bool
usingNewHandler
=
false
;
// Creates a spy onError. This spy needs to be set before widgets binding
// initializes.
FlutterError
.
onError
=
(
FlutterErrorDetails
details
)
{
usingNewHandler
=
true
;
};
// Verify structured errors are shown.
expect
(
onErrorCalled
,
true
);
// Structured errors are not supported on web.
if
(!
kIsWeb
)
{
expect
(
service
.
getEventsDispatched
(
'Flutter.Error'
),
hasLength
(
1
));
}
else
{
expect
(
service
.
getEventsDispatched
(
'Flutter.Error'
),
isEmpty
);
}
WidgetsFlutterBinding
.
ensureInitialized
();
try
{
// Enables structured errors.
// Verify disabling structured errors sets the default FlutterError.presentError
expect
(
await
service
.
testBoolExtension
(
'structuredErrors'
,
<
String
,
String
>{
'enabled'
:
'true'
}),
equals
(
'true'
),
);
expect
(
FlutterError
.
presentError
,
isNot
(
equals
(
oldHandler
)));
// Creates an error.
final
FlutterErrorDetails
expectedError
=
FlutterErrorDetails
(
library
:
'rendering library'
,
context:
ErrorDescription
(
'during layout'
),
exception:
StackTrace
.
current
,
expect
(
await
service
.
testBoolExtension
(
'structuredErrors'
,
<
String
,
String
>{
'enabled'
:
'false'
}),
equals
(
'false'
),
);
FlutterError
.
reportError
(
expectedError
);
// For non-web apps, this validates the new handler did not receive an
// error because `FlutterError.onError` was set to
// `WidgetInspectorService._structuredExceptionHandler` when service
// extensions were initialized. For web apps, the new handler should
// have received an error because structured errors are disabled by
// default on the web.
expect
(
usingNewHandler
,
equals
(
kIsWeb
));
expect
(
FlutterError
.
presentError
,
equals
(
oldHandler
));
}
finally
{
FlutterError
.
onError
=
oldHandler
;
}
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment