Skip to content

Commit 4a79540

Browse files
Fix dataTransfer RTE take 2: work around issue in #154 that necessitated revert of #153
1 parent 7531479 commit 4a79540

File tree

2 files changed

+66
-29
lines changed

2 files changed

+66
-29
lines changed

lib/react_client.dart

Lines changed: 61 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -637,38 +637,72 @@ SyntheticFormEvent syntheticFormEventFactory(events.SyntheticFormEvent e) {
637637
}
638638

639639
/// Wrapper for [SyntheticDataTransfer].
640-
SyntheticDataTransfer syntheticDataTransferFactory(events.SyntheticDataTransfer dt) {
640+
///
641+
/// [dt] is typed as Object instead of [dynamic] to avoid dynamic calls in the method body,
642+
/// ensuring the code is statically sound.
643+
SyntheticDataTransfer syntheticDataTransferFactory(Object dt) {
641644
if (dt == null) return null;
642-
List<File> files = [];
643-
if (dt.files != null) {
644-
for (int i = 0; i < dt.files.length; i++) {
645-
files.add(dt.files[i]);
645+
646+
List rawFiles;
647+
List rawTypes;
648+
649+
String effectAllowed;
650+
String dropEffect;
651+
652+
// Handle dt being either a native DOM DataTransfer object or a JS object that looks like it (events.NonNativeDataTransfer).
653+
// Casting a JS object to DataTransfer fails intermittently in dart2js, and vice-versa fails intermittently in either DDC or dart2js.
654+
// TODO figure out when NonNativeDataTransfer is used.
655+
//
656+
// Some logic here is duplicated to ensure static access of same-named members.
657+
if (dt is DataTransfer) {
658+
rawFiles = dt.files;
659+
rawTypes = dt.types;
660+
661+
try {
662+
// Works around a bug in IE where dragging from outside the browser fails.
663+
// Trying to access this property throws the error "Unexpected call to method or property access.".
664+
effectAllowed = dt.effectAllowed;
665+
} catch (_) {
666+
effectAllowed = 'uninitialized';
646667
}
647-
}
648-
List<String> types = [];
649-
if (dt.types != null) {
650-
for (int i = 0; i < dt.types.length; i++) {
651-
types.add(dt.types[i]);
668+
try {
669+
// For certain types of drag events in IE (anything but ondragenter, ondragover, and ondrop), this fails.
670+
// Trying to access this property throws the error "Unexpected call to method or property access.".
671+
dropEffect = dt.dropEffect;
672+
} catch (_) {
673+
dropEffect = 'none';
674+
}
675+
} else {
676+
// Assume it's a NonNativeDataTransfer otherwise.
677+
// Perform a cast inside `else` instead of an `else if (dt is ...)` since is-checks for
678+
// anonymous JS objects have undefined behavior.
679+
final castedDt = dt as events.NonNativeDataTransfer;
680+
681+
rawFiles = castedDt.files;
682+
rawTypes = castedDt.types;
683+
684+
try {
685+
// Works around a bug in IE where dragging from outside the browser fails.
686+
// Trying to access this property throws the error "Unexpected call to method or property access.".
687+
effectAllowed = castedDt.effectAllowed;
688+
} catch (_) {
689+
effectAllowed = 'uninitialized';
690+
}
691+
try {
692+
// For certain types of drag events in IE (anything but ondragenter, ondragover, and ondrop), this fails.
693+
// Trying to access this property throws the error "Unexpected call to method or property access.".
694+
dropEffect = castedDt.dropEffect;
695+
} catch (_) {
696+
dropEffect = 'none';
652697
}
653-
}
654-
var effectAllowed;
655-
var dropEffect;
656-
657-
try {
658-
// Works around a bug in IE where dragging from outside the browser fails.
659-
// Trying to access this property throws the error "Unexpected call to method or property access.".
660-
effectAllowed = dt.effectAllowed;
661-
} catch (exception) {
662-
effectAllowed = 'uninitialized';
663698
}
664699

665-
try {
666-
// For certain types of drag events in IE (anything but ondragenter, ondragover, and ondrop), this fails.
667-
// Trying to access this property throws the error "Unexpected call to method or property access.".
668-
dropEffect = dt.dropEffect;
669-
} catch (exception) {
670-
dropEffect = 'none';
671-
}
700+
// Copy these lists and ensure they're typed properly.
701+
// todo use .cast() in Dart 2
702+
final files = <File>[];
703+
final types = <String>[];
704+
rawFiles?.forEach(files.add);
705+
rawTypes?.forEach(types.add);
672706

673707
return new SyntheticDataTransfer(dropEffect, effectAllowed, files, types);
674708
}

lib/src/react_client/synthetic_event_wrappers.dart

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -59,9 +59,12 @@ class SyntheticFocusEvent extends SyntheticEvent {
5959
@anonymous
6060
class SyntheticFormEvent extends SyntheticEvent {}
6161

62+
/// A JS object that looks like a [DataTransfer] but isn't one.
63+
///
64+
/// See `syntheticDataTransferFactory` for more info.
6265
@JS()
6366
@anonymous
64-
class SyntheticDataTransfer {
67+
class NonNativeDataTransfer {
6568
external String get dropEffect;
6669
external String get effectAllowed;
6770
external List<File> get files;
@@ -77,7 +80,7 @@ class SyntheticMouseEvent extends SyntheticEvent {
7780
external num get clientX;
7881
external num get clientY;
7982
external bool get ctrlKey;
80-
external SyntheticDataTransfer get dataTransfer;
83+
external dynamic get dataTransfer;
8184
external bool get metaKey;
8285
external num get pageX;
8386
external num get pageY;

0 commit comments

Comments
 (0)