1

I have been using new File(file.path); in bootstrapped privileged code from Firefox 17.* to 51.*.
file is an nsIFile.

As of Firefox 52, it now gives an error: TypeError: Not enough arguments to File.

ref: Firefox 52 for developers

The File and Directory Entries API has been updated to include changes in the latest spec (see bug 1284987 for the exact details).

What would be an example of the proper code to use now for Firefox 52.*+?

Update upon request:

// note: aFileURL is a local file
let aFileURL = 'file:///C:/Users/***/icon.png'; // just an example
let file = Services.io.newURI(aFileURL, null, null)
            .QueryInterface(Components.interfaces.nsIFileURL).file; // convert URL to nsIFile
file = new File(file.path); // Firefox 52: TypeError: Not enough arguments to File.
erosman
  • 7,094
  • 7
  • 27
  • 46
  • Please provide more code. While a complete [mcve] might be a bit much, we at least need to have you show/confirm where `File` is defined. We can *guess*, but it would just be an educated guess. – Makyen Feb 18 '17 at 17:09
  • I have added more code. although the only thing that it shows is that `file` is an `nsIFile` which was mentioned in the original post. Note: the code has been working since Firefox 17 up to Firefox 51 and only the changes in Firefox 52 has caused the error. – erosman Feb 18 '17 at 17:31
  • 1
    Based on [the documentation](https://developer.mozilla.org/en-US/docs/Extensions/Using_the_DOM_File_API_in_chrome_code) it appears that you should be using `var file = File.createFromNsIFile(dsFile);` or `var file = File.createFromFileName("path/to/some/file");` – Makyen Feb 18 '17 at 19:12
  • I tried both and both run into error – erosman Feb 18 '17 at 19:41
  • What, *exactly*, was shown in the [Browser Console](https://developer.mozilla.org/en-US/docs/Tools/Browser_Console) (Ctrl-Shift-J, or Cmd-Shift-J on OSX)? – Makyen Feb 18 '17 at 19:44
  • Please provide a [mcve] which can be used to duplicate the problem using some static file name. This will allow others to work on the issue without having to write a bunch of code to do so. – Makyen Feb 18 '17 at 19:46
  • Thank you @Makyen. I think the point is missed. There is no point in testing a code (unless the error is in the code). The point is that Firefox has changed its implementation of `new File()` in its version 52. Only knowing what they have changed is relevant for providing the answer. The change is listed in the link provided. I need a sample/example code to adapt my code. – erosman Feb 19 '17 at 05:38
  • 1
    You have not said what error you are getting for `file = File.createFromFileName(file.path);` or `file = File.createFromNsIFile(file);` Using `var foo = File.createFromFileName();console.log(foo);` works just fine for me in FF53.0a2. – Makyen Feb 19 '17 at 06:16
  • The code given in the initial post is reproducible (eg via sctrachpad). I am going to try the `file = File.createFromFileName(file.path);` again. – erosman Feb 19 '17 at 06:47
  • 1
    My request for a MCVE was because you stated that both `File.createFromNsIFile()` and `File.createFromFileName()` produce errors for you. They work fine for me. You did not specify the error(s), so I asked for a MCVE to be able to reproduce those issues. Yes, the code ``var foo = new File();` does not work, produces the not very helpful error that you have too few arguments. If you are wanting to use the `new File()` constructor, you can use: `var foo = new File([],);`. I've found the spec. and tested code. I'll write up an answer. – Makyen Feb 19 '17 at 06:56
  • You are correct. I tested it and it works. I had made a mistake :( Thank you @Makyen – erosman Feb 19 '17 at 07:00

1 Answers1

0

Thanks to Makyen

ref: Using the DOM File API in chrome code

MDN stated: var file = File.createFromFileName("path/to/some/file");

The following code didn't work: (my misunderstanding)

// Using text URL
Components.utils.importGlobalProperties(['File']);
let aFileURL = 'file:///C:/Users/***/icon.png'; // just an example
let file = File.createFromFileName(aFileURL);
// "File error: Unrecognized path"  nsresult: "0x80520001 (NS_ERROR_FILE_UNRECOGNIZED_PATH)"

The following code works:

Components.utils.importGlobalProperties(['File']);
let aFileURL = 'file:///C:/Users/***/icon.png'; // just an example
let file = Services.io.newURI(aFileURL, null, null)
            .QueryInterface(Components.interfaces.nsIFileURL).file; // convert URL to nsIFile
file = File.createFromFileName(file.path);

The following code also works:

Components.utils.importGlobalProperties(['File']);
let aFileURL = 'file:///C:/Users/***/icon.png'; // just an example
let file = Services.io.newURI(aFileURL, null, null)
            .QueryInterface(Components.interfaces.nsIFileURL).file; // convert URL to nsIFile
file = File.createFromNsIFile(file);

Additional info for reference:

Using file = new File([], file.path); produces the following:

File { name: "C:\Users\...\icon.png", lastModified: 1487509240391, lastModifiedDate: Date 2017-02-19T13:00:40.391Z, webkitRelativePath: "", mozFullPath: "", size: 0, type: "" }

However, using file = File.createFromFileName(file.path); produces the following:

File { name: "icon.png", lastModified: 1403974172431, lastModifiedDate: Date 2014-06-28T16:49:32.431Z, webkitRelativePath: "", mozFullPath: "", size: 4294, type: "image/png" }

Using file = File.createFromNsIFile(file); produces the following:

File { name: "icon.png", lastModified: 1403974172431, lastModifiedDate: Date 2014-06-28T16:49:32.431Z, webkitRelativePath: "", mozFullPath: "C:\Users\...\icon.png", size: 4294, type: "image/png" }

Passing the file from the first code to FileReader() produces the wrong result. "data:application/octet-stream;base64,"

Passing the file from the 2nd & 3rd code to FileReader() produces the correct result. "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAEAAAABACAYAAACqaXHeAAAQjUlEQVR42uWbB3QU17nHv7uzq60S6sJGotniARGYUCQcZAvkhh0QosZgXPJsHwgJpiTB4Aq4JrafwTHvkZeYBBt4EELAGAwGhABjwEYgcMExEk1CjSIJaXuZyXdHO8v..."

erosman
  • 7,094
  • 7
  • 27
  • 46
  • 1
    References: [`File()` constructor syntax](https://developer.mozilla.org/en-US/docs/Web/API/File#Implementation_notes) showing 3 arguments. [W3C File API spec](https://w3c.github.io/FileAPI/#file-constructor) explicitly stating the need for 2 or 3 arguments (this implicitly conflicts with the notes in the `File` Implementation notes that states privileged code can pass the `File()` constructor an `nsIFile` Object). You might want to mention that you can also do `var foo = File([],file.path)`. Feel free to copy/restate any of this info into your answer. – Makyen Feb 19 '17 at 07:58
  • I got error with `File([],file.path)` saying `"Component returned failure code: 0x80040111 (NS_ERROR_NOT_AVAILABLE) [nsIXPCComponents_Utils.importGlobalProperties]"` – erosman Feb 19 '17 at 10:43
  • Interesting. It worked fine for me when testing it in the Browser Console with a static string. The exact code I used was `var foo = new File([],'B:\\test.bak'); console.log(foo);`. The output was the generated `File` Object which included accurate data for that file. – Makyen Feb 19 '17 at 10:47
  • Ah.. your first code didnt have "new" in it. Additionally, the code runs without error but does not produce the right result (ie doesn't produce the right file) – erosman Feb 19 '17 at 12:40
  • Arrgg. Looks like I wrote it with `new` twice (in a comment on the question, then the 2nd comment on this answer), but without `new` in my first comment on this answer. Sorry for the confusion. Also, it is clear that I did not look closely enough at the data received from that line of code. Thank you for pointing that out. It clearly does not return the correct information. If that format is desired to be used (`new File(...` is used multiple times in the Firefox code), it will need to be looked at in more detail. – Makyen Feb 19 '17 at 13:17
  • @Makyen .. Did you find out anything new about `new File()`? I need it to use it for a WebExtension conversion. – erosman Mar 07 '17 at 10:38