Issue metadata
Sign in to add a comment
|
files instanceof FileList returns false while the type of the object is FileList
Reported by
matthijs...@gmail.com,
Apr 28 2017
|
||||||||||||||||||||||||
Issue descriptionUserAgent: Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/57.0.2987.133 Safari/537.36 Steps to reproduce the problem: 1. Make a page with ckeditor 2. Handle the drop event 3. Check evt.data.dataTransfer.$.files instanceof FileList What is the expected behavior? It returns true What went wrong? It returns false Did this work before? N/A Chrome version: 57.0.2987.133 Channel: stable OS Version: 6.1 (Windows 7, Windows Server 2008 R2) Flash Version: Shockwave Flash 25.0 r0 I posted a question stackoverflow about it with no answer (and barely any views): http://stackoverflow.com/q/43587286/210336 It does work in FireFox. I made a jsfiddle that shows the problem (returns false in Chrome and true in FireFox): https://jsfiddle.net/7dq3xyo5/3/ When I make my own div and handle the drop event, it does seem to work: https://jsfiddle.net/9nu1besp/ So it seems CKEditor does something different that triggers the bug.
,
Apr 28 2017
I can't find a Firefox bug for this, filed https://bugzilla.mozilla.org/show_bug.cgi?id=1360715 Edge, Safari and Chrome all behave the same in this regard, so I'm quite sure it's a bug in Firefox (though I haven't double checked the Ecmascript spec).
,
Apr 30 2017
This might not be the right place for this question, but what then is the right approach in this situation? Intuitively it seems really strange that as a developer you'd want this to return false in certain situations. The spec says "This may not make sense at first but when you start dealing with multiple frames or windows in your script and pass objects from one context to another via functions, this will be a valid and strong issue. For instance, you can securely check if a given object is in fact an Array using Array.isArray(myObj)". But that doesn't explain to me at all what would go wrong if the spec would say it should return true. Also, Array.isArray(myObj) won't work in a situation where there is no canonical isType function. I've got my isFileList function now that just checks __proto__.toString() == "[object FileList]". Is this then the recommended approach? Maybe I should post another SO question. PS: Do you plan to answer the SO question I linked? Otherwise I'll add an answer myself.
,
May 1 2017
Just for completeness, the Firefox behavior is in fact the one defined in the Web IDL spec at the moment (and for quite a while now). See https://heycam.github.io/webidl/#es-interface-hasinstance (which is defined in ES5 terms; this part hasn't been updated to ES6 yet because of pushback from non-Firefox browsers on implementing this part of the spec in the first place). > I've got my isFileList function now that just checks __proto__.toString() == "[object FileList]". That won't do the right thing either. Not least because the IDL spec, and every non-Chrome browser, will return "[object FileListPrototype]" in that situation.... You could do something like Object.prototype.toString.call(myObj) == "[object FileList]" if you really have to work this with all the browsers right now. But in general, the type-detection situation in the web platform is horrible, and the lack of cooperation for years now between various browsers on attempts to solve it is rather disheartening.
,
May 1 2017
Thanks for the details Boris! I should have known to check the WebIDL spec rather than assume Firefox being the odd one out meant it was your bug ;-) I couldn't find any discussion of this in our bug tracker, so filed a new bug ( issue 717016 ) to track the spec/blink behavior mismatch. Let's call this (and the question in #3) a specific instance of that larger issue.
,
May 1 2017
> what then is the right approach in this situation? Intuitively it seems really strange that as a developer you'd want this to return false in certain situations. Can you elaborate on why you want to use instanceof? From a pure JavaScript perspective, it is NOT an instance of the FileList type you have in your window. But it behaves pretty much the same as it, so you should probably just check if it has the properties you want and try to use them (known as Duck Typing https://en.wikipedia.org/wiki/Duck_typing).
,
May 1 2017
FileList is also a type we'd love to delete from the web platform - see https://github.com/w3c/FileAPI/issues/19 - it provides no benefit over e.g. a plain array of File objects. |
|||||||||||||||||||||||||
►
Sign in to add a comment |
|||||||||||||||||||||||||
Comment 1 by rbyers@chromium.org
, Apr 28 2017This isn't just about the FileList but the entire DragEvent. Debugging this I found that CKEditor is creating an iframe, and so the event types delivered to the iframe have different prototype objects than the main window where the event handler is running. Breaking on the 'drop' event listener (before any of the JS runs and potentially mucks with the event): Object.getPrototypeOf(c)===window.DragEvent.prototype > false Object.getPrototypeOf(c)===document.querySelector('iframe.cke_wysiwyg_frame').contentWindow.DragEvent.prototype > true See the documentation of instanceof and multiple contexts here: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/instanceof#instanceof_and_multiple_context_(e.g._frames_or_windows) However, I indeed see that instance of returns true for such cases in Firefox. Here's a really simple reproduction: http://jsbin.com/yefesuv Looking for a firefox bug now...