@@ -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}
0 commit comments