New issue
Advanced search Search tips

Issue 716423 link

Starred by 1 user

Issue metadata

Status: Duplicate
Merged: issue 717016
Owner: ----
Closed: Apr 2017
Cc:
Components:
EstimatedDays: ----
NextAction: ----
OS: Windows
Pri: 2
Type: Bug



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 description

UserAgent: 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.
 

Comment 1 by rbyers@chromium.org, Apr 28 2017

Components: -Blink Blink>DataTransfer
This 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...

Comment 2 by rbyers@chromium.org, Apr 28 2017

Cc: rbyers@chromium.org
Status: WontFix (was: Unconfirmed)
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).
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.

Comment 4 by bzbar...@mit.edu, 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.
Mergedinto: 717016
Status: Duplicate (was: WontFix)
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.
> 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).

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