Skip to content

Commit

Permalink
Merge 001e443 into 56810ff
Browse files Browse the repository at this point in the history
  • Loading branch information
denrase authored Oct 11, 2022
2 parents 56810ff + 001e443 commit cee7e1b
Show file tree
Hide file tree
Showing 8 changed files with 368 additions and 144 deletions.
4 changes: 4 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,10 @@

## Unreleased

### Features

- Use PlatformDispatcher.onError in Flutter 3.3 ([#1039](https://github.com/getsentry/sentry-dart/pull/1039))

### Fixes

- Avoid dependency conflict with package_info_plus v2 ([#1068](https://github.com/getsentry/sentry-dart/pull/1068))
Expand Down
39 changes: 23 additions & 16 deletions dart/lib/src/sentry.dart
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ class Sentry {
static Future<void> init(
OptionsConfiguration optionsConfiguration, {
AppRunner? appRunner,
@internal bool callAppRunnerInRunZonedGuarded = true,
@internal SentryOptions? options,
}) async {
final sentryOptions = options ?? SentryOptions();
Expand All @@ -56,7 +57,7 @@ class Sentry {
throw ArgumentError('DSN is required.');
}

await _init(sentryOptions, appRunner);
await _init(sentryOptions, appRunner, callAppRunnerInRunZonedGuarded);
}

static Future<void> _initDefaultValues(
Expand Down Expand Up @@ -96,7 +97,8 @@ class Sentry {
}

/// Initializes the SDK
static Future<void> _init(SentryOptions options, AppRunner? appRunner) async {
static Future<void> _init(SentryOptions options, AppRunner? appRunner,
bool callAppRunnerInRunZonedGuarded) async {
if (isEnabled) {
options.logger(
SentryLevel.warning,
Expand All @@ -113,21 +115,26 @@ class Sentry {

// execute integrations after hub being enabled
if (appRunner != null) {
var runIntegrationsAndAppRunner = () async {
final integrations =
options.integrations.where((i) => i is! RunZonedGuardedIntegration);
await _callIntegrations(integrations, options);
if (callAppRunnerInRunZonedGuarded) {
var runIntegrationsAndAppRunner = () async {
final integrations = options.integrations
.where((i) => i is! RunZonedGuardedIntegration);
await _callIntegrations(integrations, options);
await appRunner();
};

final runZonedGuardedIntegration =
RunZonedGuardedIntegration(runIntegrationsAndAppRunner);
options.addIntegrationByIndex(0, runZonedGuardedIntegration);

// RunZonedGuardedIntegration will run other integrations and appRunner
// runZonedGuarded so all exception caught in the error handler are
// handled
await runZonedGuardedIntegration(HubAdapter(), options);
} else {
await _callIntegrations(options.integrations, options);
await appRunner();
};

final runZonedGuardedIntegration =
RunZonedGuardedIntegration(runIntegrationsAndAppRunner);
options.addIntegrationByIndex(0, runZonedGuardedIntegration);

// RunZonedGuardedIntegration will run other integrations and appRunner
// runZonedGuarded so all exception caught in the error handler are
// handled
await runZonedGuardedIntegration(HubAdapter(), options);
}
} else {
await _callIntegrations(options.integrations, options);
}
Expand Down
25 changes: 25 additions & 0 deletions dart/test/sentry_test.dart
Original file line number Diff line number Diff line change
Expand Up @@ -284,6 +284,31 @@ void main() {
});
});

test('should complete when appRunner is not called in runZonedGuarded',
() async {
final completer = Completer();
var completed = false;

final init = Sentry.init(
(options) {
options.dsn = fakeDsn;
},
appRunner: () => completer.future,
callAppRunnerInRunZonedGuarded: false,
).whenComplete(() => completed = true);

await Future(() {
// We make the expectation only after all microtasks have completed,
// that Sentry.init might have scheduled.
expect(completed, false);
});

completer.complete();
await init;

expect(completed, true);
});

test('options.environment debug', () async {
final sentryOptions = SentryOptions(dsn: fakeDsn)
..platformChecker = FakePlatformChecker.debugMode();
Expand Down
4 changes: 0 additions & 4 deletions flutter/lib/src/integrations/on_error_integration.dart
Original file line number Diff line number Diff line change
Expand Up @@ -38,10 +38,6 @@ class OnErrorIntegration implements Integration<SentryFlutterOptions> {
// WidgetsBinding works with WidgetsFlutterBinding and other custom bindings
final wrapper = dispatchWrapper ??
PlatformDispatcherWrapper(binding.platformDispatcher);

if (!wrapper.isOnErrorSupported(options)) {
return;
}
_defaultOnError = wrapper.onError;

_integrationOnError = (Object exception, StackTrace stackTrace) {
Expand Down
36 changes: 21 additions & 15 deletions flutter/lib/src/sentry_flutter.dart
Original file line number Diff line number Diff line change
@@ -1,10 +1,11 @@
import 'dart:async';
import 'dart:ui';

import 'package:flutter/scheduler.dart';
import 'package:flutter/services.dart';
import 'package:meta/meta.dart';
import 'package:package_info_plus/package_info_plus.dart';
import 'package:sentry/sentry.dart';
import '../sentry_flutter.dart';
import 'event_processor/android_platform_exception_event_processor.dart';
import 'native_scope_observer.dart';
import 'sentry_native.dart';
Expand All @@ -13,9 +14,7 @@ import 'sentry_native_channel.dart';
import 'event_processor/flutter_enricher_event_processor.dart';
import 'integrations/debug_print_integration.dart';
import 'integrations/native_app_start_integration.dart';
import 'sentry_flutter_options.dart';

import 'default_integrations.dart';
import 'file_system_transport.dart';

import 'version.dart';
Expand Down Expand Up @@ -45,27 +44,28 @@ mixin SentryFlutter {
final native = SentryNative();
native.setNativeChannel(nativeChannel);

final platformDispatcher = PlatformDispatcher.instance;
final wrapper = PlatformDispatcherWrapper(platformDispatcher);
final isOnErrorSupported = wrapper.isOnErrorSupported(flutterOptions);

// first step is to install the native integration and set default values,
// so we are able to capture future errors.
final defaultIntegrations = _createDefaultIntegrations(
packageLoader,
channel,
flutterOptions,
);
packageLoader, channel, flutterOptions, isOnErrorSupported);
for (final defaultIntegration in defaultIntegrations) {
flutterOptions.addIntegration(defaultIntegration);
}

await _initDefaultValues(flutterOptions, channel);

await Sentry.init(
(options) async {
await optionsConfiguration(options as SentryFlutterOptions);
},
appRunner: appRunner,
// ignore: invalid_use_of_internal_member
options: flutterOptions,
);
await Sentry.init((options) async {
await optionsConfiguration(options as SentryFlutterOptions);
},
appRunner: appRunner,
// ignore: invalid_use_of_internal_member
options: flutterOptions,
// ignore: invalid_use_of_internal_member
callAppRunnerInRunZonedGuarded: !isOnErrorSupported);
}

static Future<void> _initDefaultValues(
Expand Down Expand Up @@ -96,6 +96,7 @@ mixin SentryFlutter {
PackageLoader packageLoader,
MethodChannel channel,
SentryFlutterOptions options,
bool isOnErrorSupported,
) {
final integrations = <Integration>[];
final platformChecker = options.platformChecker;
Expand All @@ -104,6 +105,11 @@ mixin SentryFlutter {
// Will call WidgetsFlutterBinding.ensureInitialized() before all other integrations.
integrations.add(WidgetsFlutterBindingIntegration());

// Use PlatformDispatcher.onError instead of zones.
if (isOnErrorSupported) {
integrations.add(OnErrorIntegration());
}

// Will catch any errors that may occur in the Flutter framework itself.
integrations.add(FlutterErrorIntegration());

Expand Down
2 changes: 1 addition & 1 deletion flutter/test/mocks.mocks.dart
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
// Mocks generated by Mockito 5.3.1 from annotations
// Mocks generated by Mockito 5.3.2 from annotations
// in sentry_flutter/example/windows/flutter/ephemeral/.plugin_symlinks/sentry_flutter/example/linux/flutter/ephemeral/.plugin_symlinks/sentry_flutter/example/ios/.symlinks/plugins/sentry_flutter/test/mocks.dart.
// Do not manually edit this file.

Expand Down
Loading

0 comments on commit cee7e1b

Please sign in to comment.