From 506efc5fd7a031e48cf4a3313751d9c3f43f6190 Mon Sep 17 00:00:00 2001 From: Aaron Lademann Date: Thu, 6 Jun 2024 17:57:42 -0700 Subject: [PATCH 1/2] Work around non-nullable dataTransfer property MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Its possible in JS for MouseEvent.dataTransfer to be null - but in Dart SDK’s interop, its non nullable. --- lib/src/react_client/event_helpers.dart | 28 ++++++++++++++++++++++- test/react_client/event_helpers_test.dart | 8 +++++++ 2 files changed, 35 insertions(+), 1 deletion(-) diff --git a/lib/src/react_client/event_helpers.dart b/lib/src/react_client/event_helpers.dart index d7c2d5ff..2295d0b0 100644 --- a/lib/src/react_client/event_helpers.dart +++ b/lib/src/react_client/event_helpers.dart @@ -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'; @@ -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, @@ -823,3 +824,28 @@ extension DataTransferHelper on SyntheticMouseEvent { /// See 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 will 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; + } +} \ No newline at end of file diff --git a/test/react_client/event_helpers_test.dart b/test/react_client/event_helpers_test.dart index 4613e5d0..6fe4dfa6 100644 --- a/test/react_client/event_helpers_test.dart +++ b/test/react_client/event_helpers_test.dart @@ -2105,6 +2105,14 @@ 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); + }); + }); } enum SyntheticEventType { From 98369193f95a656016a1fa720d4c98cf6f5092e8 Mon Sep 17 00:00:00 2001 From: Aaron Lademann Date: Fri, 7 Jun 2024 09:09:10 -0700 Subject: [PATCH 2/2] Fffffffffffffffffffffformat --- lib/src/react_client/event_helpers.dart | 4 ++-- test/react_client/event_helpers_test.dart | 3 ++- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/lib/src/react_client/event_helpers.dart b/lib/src/react_client/event_helpers.dart index 2295d0b0..69efc8fd 100644 --- a/lib/src/react_client/event_helpers.dart +++ b/lib/src/react_client/event_helpers.dart @@ -838,7 +838,7 @@ extension SafeNativeDataTransfer on MouseEvent { /// Unexpected null value encountered in Dart web platform libraries. /// ``` /// - /// This extension is used will catch the error within our [wrapNativeMouseEvent] function so that + /// 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 { @@ -848,4 +848,4 @@ extension SafeNativeDataTransfer on MouseEvent { } catch (_) {} return dataTransfer; } -} \ No newline at end of file +} diff --git a/test/react_client/event_helpers_test.dart b/test/react_client/event_helpers_test.dart index 6fe4dfa6..06eaf910 100644 --- a/test/react_client/event_helpers_test.dart +++ b/test/react_client/event_helpers_test.dart @@ -2108,7 +2108,8 @@ main() { // See: `SafeNativeDataTransfer` extension group('SafeNativeDataTransfer MouseEvent extension', () { - test('prevents faulty Dart SDK web platform null exceptions when ' + 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); });