Skip to content

Commit

Permalink
Merge pull request #398 from Workiva/null-safe-dataTransfer
Browse files Browse the repository at this point in the history
FED-2812 Catch MouseEvent.dataTransfer null exception
  • Loading branch information
rmconsole6-wk authored Jun 7, 2024
2 parents 2a0b883 + 9836919 commit dcc645b
Show file tree
Hide file tree
Showing 2 changed files with 36 additions and 1 deletion.
28 changes: 27 additions & 1 deletion lib/src/react_client/event_helpers.dart
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ library react_client.event_helpers;
import 'dart:html';

import 'package:js/js_util.dart';
import 'package:meta/meta.dart';
import 'package:react/react_client/js_interop_helpers.dart';
import 'package:react/src/react_client/synthetic_data_transfer.dart';
import 'package:react/src/react_client/synthetic_event_wrappers.dart';
Expand Down Expand Up @@ -72,7 +73,7 @@ SyntheticMouseEvent wrapNativeMouseEvent(MouseEvent nativeEvent) {
'clientX': nativeEvent.client.x,
'clientY': nativeEvent.client.y,
'ctrlKey': nativeEvent.ctrlKey,
'dataTransfer': nativeEvent.dataTransfer,
'dataTransfer': nativeEvent.safeDataTransfer,
'metaKey': nativeEvent.metaKey,
'pageX': nativeEvent.page.x,
'pageY': nativeEvent.page.y,
Expand Down Expand Up @@ -823,3 +824,28 @@ extension DataTransferHelper on SyntheticMouseEvent {
/// See <https://developer.mozilla.org/en-US/docs/Web/API/DragEvent/dataTransfer>
SyntheticDataTransfer? get dataTransfer => syntheticDataTransferFactory(getProperty(this, 'dataTransfer'));
}

extension SafeNativeDataTransfer on MouseEvent {
/// In Dart SDK versions with null-safety enabled,
/// [the interop](https://github.com/dart-lang/sdk/blob/master/sdk/lib/html/dart2js/html_dart2js.dart#L22421-L22422)
/// for [MouseEvent.dataTransfer] is non-nullable despite the
/// [JS spec for `dataTransfer`](https://developer.mozilla.org/en-US/docs/Web/API/DragEvent/dataTransfer)
/// clearly indicating that it can be null.
///
/// This can cause the SDK to throw when a `MouseEvent` is manually constructed, and the `dataTransfer`
/// getter is then accessed when running with `sound_null_safety` enabled:
/// ```
/// Unexpected null value encountered in Dart web platform libraries.
/// ```
///
/// This extension is used to catch the error within our [wrapNativeMouseEvent] function so that
/// `SyntheticMouseEvent`s do not throw the null exception.
@internal
DataTransfer? get safeDataTransfer {
DataTransfer? dataTransfer;
try {
dataTransfer = this.dataTransfer;
} catch (_) {}
return dataTransfer;
}
}
9 changes: 9 additions & 0 deletions test/react_client/event_helpers_test.dart
Original file line number Diff line number Diff line change
Expand Up @@ -2105,6 +2105,15 @@ main() {
});
});
});

// See: `SafeNativeDataTransfer` extension
group('SafeNativeDataTransfer MouseEvent extension', () {
test(
'prevents faulty Dart SDK web platform null exceptions when '
'accessing the `dataTransfer` getter on a manually constructed MouseEvent', () {
expect(() => wrapNativeMouseEvent(MouseEvent('click')).dataTransfer, returnsNormally);
});
});
}

class MockDataTransfer extends Mock implements DataTransfer {}
Expand Down

0 comments on commit dcc645b

Please sign in to comment.