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
...
@@ -867,7 +867,9 @@ class FlutterError extends Error with DiagnosticableTreeMixin implements Asserti
/// The default behavior is to call [presentError].
/// The default behavior is to call [presentError].
///
///
/// You can set this to your own function to override this default behavior.
/// 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
/// If the error handler throws an exception, it will not be caught by the
/// Flutter framework.
/// Flutter framework.
...
@@ -877,6 +879,11 @@ class FlutterError extends Error with DiagnosticableTreeMixin implements Asserti
...
@@ -877,6 +879,11 @@ class FlutterError extends Error with DiagnosticableTreeMixin implements Asserti
///
///
/// Do not call [onError] directly, instead, call [reportError], which
/// Do not call [onError] directly, instead, call [reportError], which
/// forwards to [onError] if it is not null.
/// 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
;
static
FlutterExceptionHandler
?
onError
=
presentError
;
/// Called by the Flutter framework before attempting to parse a [StackTrace].
/// 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 {
...
@@ -746,8 +746,6 @@ mixin WidgetInspectorService {
bool
_trackRebuildDirtyWidgets
=
false
;
bool
_trackRebuildDirtyWidgets
=
false
;
bool
_trackRepaintWidgets
=
false
;
bool
_trackRepaintWidgets
=
false
;
FlutterExceptionHandler
?
_structuredExceptionHandler
;
late
RegisterServiceExtensionCallback
_registerServiceExtensionCallback
;
late
RegisterServiceExtensionCallback
_registerServiceExtensionCallback
;
/// Registers a service extension method with the given name (full
/// Registers a service extension method with the given name (full
/// name "ext.flutter.inspector.name").
/// name "ext.flutter.inspector.name").
...
@@ -920,7 +918,7 @@ mixin WidgetInspectorService {
...
@@ -920,7 +918,7 @@ mixin WidgetInspectorService {
int
_errorsSinceReload
=
0
;
int
_errorsSinceReload
=
0
;
void
_reportError
(
FlutterErrorDetails
details
)
{
void
_report
Structured
Error
(
FlutterErrorDetails
details
)
{
final
Map
<
String
,
Object
?>
errorJson
=
_nodeToJson
(
final
Map
<
String
,
Object
?>
errorJson
=
_nodeToJson
(
details
.
toDiagnosticsNode
(),
details
.
toDiagnosticsNode
(),
InspectorSerializationDelegate
(
InspectorSerializationDelegate
(
...
@@ -981,9 +979,10 @@ mixin WidgetInspectorService {
...
@@ -981,9 +979,10 @@ mixin WidgetInspectorService {
/// * [BindingBase.initServiceExtensions], which explains when service
/// * [BindingBase.initServiceExtensions], which explains when service
/// extensions can be used.
/// extensions can be used.
void
initServiceExtensions
(
RegisterServiceExtensionCallback
registerServiceExtensionCallback
)
{
void
initServiceExtensions
(
RegisterServiceExtensionCallback
registerServiceExtensionCallback
)
{
_structuredExceptionHandler
=
_reportError
;
final
FlutterExceptionHandler
defaultExceptionHandler
=
FlutterError
.
presentError
;
if
(
isStructuredErrorsEnabled
())
{
if
(
isStructuredErrorsEnabled
())
{
FlutterError
.
onError
=
_structuredExceptionHandle
r
;
FlutterError
.
presentError
=
_reportStructuredErro
r
;
}
}
_registerServiceExtensionCallback
=
registerServiceExtensionCallback
;
_registerServiceExtensionCallback
=
registerServiceExtensionCallback
;
assert
(!
_debugServiceExtensionsRegistered
);
assert
(!
_debugServiceExtensionsRegistered
);
...
@@ -994,13 +993,11 @@ mixin WidgetInspectorService {
...
@@ -994,13 +993,11 @@ mixin WidgetInspectorService {
SchedulerBinding
.
instance
!.
addPersistentFrameCallback
(
_onFrameStart
);
SchedulerBinding
.
instance
!.
addPersistentFrameCallback
(
_onFrameStart
);
final
FlutterExceptionHandler
defaultExceptionHandler
=
FlutterError
.
presentError
;
_registerBoolServiceExtension
(
_registerBoolServiceExtension
(
name:
'structuredErrors'
,
name:
'structuredErrors'
,
getter:
()
async
=>
FlutterError
.
presentError
==
_
structuredExceptionHandle
r
,
getter:
()
async
=>
FlutterError
.
presentError
==
_
reportStructuredErro
r
,
setter:
(
bool
value
)
{
setter:
(
bool
value
)
{
FlutterError
.
presentError
=
value
?
_
structuredExceptionHandler
!
:
defaultExceptionHandler
;
FlutterError
.
presentError
=
value
?
_
reportStructuredError
:
defaultExceptionHandler
;
return
Future
<
void
>.
value
();
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 @@
...
@@ -2,93 +2,85 @@
// Use of this source code is governed by a BSD-style license that can be
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
// found in the LICENSE file.
import
'dart:async'
;
import
'dart:convert'
;
import
'package:flutter/foundation.dart'
;
import
'package:flutter/foundation.dart'
;
import
'package:flutter/widgets.dart'
;
import
'package:flutter/widgets.dart'
;
import
'package:flutter_test/flutter_test.dart'
;
import
'package:flutter_test/flutter_test.dart'
;
import
'widget_inspector_test_utils.dart'
;
void
main
(
)
{
void
main
(
)
{
StructureErrorTestWidgetInspectorService
.
runTests
();
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
{
test
(
'ext.flutter.inspector.structuredErrors - custom FlutterError.onError'
,
()
async
{
final
Map
<
String
,
InspectorServiceExtensionCallback
>
extensions
=
<
String
,
InspectorServiceExtensionCallback
>{};
// 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
final
FlutterExceptionHandler
?
oldHandler
=
FlutterError
.
onError
;
void
registerServiceExtension
({
required
String
name
,
required
FutureOr
<
Map
<
String
,
Object
?>>
Function
(
Map
<
String
,
String
>
parameters
)
callback
,
})
{
assert
(!
extensions
.
containsKey
(
name
));
extensions
[
name
]
=
callback
;
}
@override
try
{
void
postEvent
(
String
eventKind
,
Map
<
Object
,
Object
?>
eventData
)
{
expect
(
service
.
getEventsDispatched
(
'Flutter.Error'
),
isEmpty
);
getEventsDispatched
(
eventKind
).
add
(
eventData
);
}
List
<
Map
<
Object
,
Object
?>>
getEventsDispatched
(
String
eventKind
)
{
// Set callback that doesn't call presentError.
return
eventsDispatched
.
putIfAbsent
(
eventKind
,
()
=>
<
Map
<
Object
,
Object
?>>[]);
bool
onErrorCalled
=
false
;
}
FlutterError
.
onError
=
(
FlutterErrorDetails
details
)
{
onErrorCalled
=
true
;
};
Iterable
<
Map
<
Object
,
Object
?>>
getServiceExtensionStateChangedEvents
(
String
extensionName
)
{
// Get the service registered.
return
getEventsDispatched
(
'Flutter.ServiceExtensionStateChanged'
)
WidgetsFlutterBinding
.
ensureInitialized
();
.
where
((
Map
<
Object
,
Object
?>
event
)
=>
event
[
'extension'
]
==
extensionName
);
}
Future
<
String
>
testBoolExtension
(
String
name
,
Map
<
String
,
String
>
arguments
)
async
{
final
FlutterErrorDetails
expectedError
=
FlutterErrorDetails
(
expect
(
extensions
,
contains
(
name
));
library
:
'rendering library'
,
// Encode and decode to JSON to match behavior using a real service
context:
ErrorDescription
(
'during layout'
),
// extension where only JSON is allowed.
exception:
StackTrace
.
current
,
// ignore: avoid_dynamic_calls
);
return
json
.
decode
(
json
.
encode
(
await
extensions
[
name
]!(
arguments
)))[
'enabled'
]
as
String
;
FlutterError
.
reportError
(
expectedError
);
}
// Verify structured errors are not shown.
expect
(
onErrorCalled
,
true
);
expect
(
service
.
getEventsDispatched
(
'Flutter.Error'
),
isEmpty
);
static
void
runTests
()
{
// Set callback that calls presentError.
final
StructureErrorTestWidgetInspectorService
service
=
StructureErrorTestWidgetInspectorService
();
onErrorCalled
=
false
;
WidgetInspectorService
.
instance
=
service
;
FlutterError
.
onError
=
(
FlutterErrorDetails
details
)
{
FlutterError
.
presentError
(
details
);
onErrorCalled
=
true
;
};
test
(
'ext.flutter.inspector.structuredErrors reports error to _structuredExceptionHandler on error'
,
()
async
{
FlutterError
.
reportError
(
expectedError
);
final
FlutterExceptionHandler
?
oldHandler
=
FlutterError
.
onError
;
bool
usingNewHandler
=
false
;
// Verify structured errors are shown.
// Creates a spy onError. This spy needs to be set before widgets binding
expect
(
onErrorCalled
,
true
);
// initializes.
// Structured errors are not supported on web.
FlutterError
.
onError
=
(
FlutterErrorDetails
details
)
{
if
(!
kIsWeb
)
{
usingNewHandler
=
true
;
expect
(
service
.
getEventsDispatched
(
'Flutter.Error'
),
hasLength
(
1
));
};
}
else
{
expect
(
service
.
getEventsDispatched
(
'Flutter.Error'
),
isEmpty
);
}
WidgetsFlutterBinding
.
ensureInitialized
();
// Verify disabling structured errors sets the default FlutterError.presentError
try
{
// Enables structured errors.
expect
(
expect
(
await
service
.
testBoolExtension
(
'structuredErrors'
,
<
String
,
String
>{
'enabled'
:
'true'
}),
await
service
.
testBoolExtension
(
'structuredErrors'
,
<
String
,
String
>{
'enabled'
:
'true'
}),
equals
(
'true'
),
equals
(
'true'
),
);
);
expect
(
FlutterError
.
presentError
,
isNot
(
equals
(
oldHandler
)));
// Creates an error.
expect
(
final
FlutterErrorDetails
expectedError
=
FlutterErrorDetails
(
await
service
.
testBoolExtension
(
'structuredErrors'
,
<
String
,
String
>{
'enabled'
:
'false'
}),
library
:
'rendering library'
,
equals
(
'false'
),
context:
ErrorDescription
(
'during layout'
),
exception:
StackTrace
.
current
,
);
);
FlutterError
.
reportError
(
expectedError
);
expect
(
FlutterError
.
presentError
,
equals
(
oldHandler
));
// 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
));
}
finally
{
}
finally
{
FlutterError
.
onError
=
oldHandler
;
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