-
Notifications
You must be signed in to change notification settings - Fork 3.3k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Add filesystem interface for the File System Access API #16804
Conversation
}, | ||
$FSFS: { | ||
DIR_MODE: Number("{{{ cDefine('S_IFDIR') }}}") | 511 /* 0777 */, | ||
FILE_MODE: Number("{{{ cDefine('S_IFREG') }}}") | 511 /* 0777 */, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This looks a little funny, but it's wrapped in a string because otherwise my editor barfs on parsing the rest of the file, and it was hard to work like that.
Object.keys(src.entries).forEach(function (key) { | ||
const e = src.entries[key]; | ||
const e2 = dst.entries[key]; | ||
if (!e2 || (FS.isFile(e.mode) && e['timestamp'].getTime() > e2['timestamp'].getTime())) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This line is peculiar, especially when you note that the idb interface does a simple equality check. The problem here is the the FS API does not allow you to set the mtime directly, it's just whatever the time was when it was written (as expected). So the modification time when written to disk will have to be ~syncfs time, which is strictly greater than the emscripten FS's mtime.
There's probably a race condition here, perhaps "syncfs" should be wrapped with some promise mechanism that prevents concurrent syncs? I'm not sure–I've ignored it because it can be avoided entirely if you just don't do concurrent syncs.
@@ -57,7 +57,7 @@ However, due to JavaScript's event-driven nature, most *persistent* storage opti | |||
File systems | |||
============ | |||
|
|||
.. note:: Only the :ref:`MEMFS <filesystem-api-memfs>` filesystem is included by default. All others must be enabled explicitly, using ``-lnodefs.js`` (:ref:`NODEFS <filesystem-api-nodefs>`), ``-lidbfs.js`` (:ref:`IDBFS <filesystem-api-idbfs>`), ``-lworkerfs.js`` (:ref:`WORKERFS <filesystem-api-workerfs>`), or ``-lproxyfs.js`` (:ref:`PROXYFS <filesystem-api-proxyfs>`). | |||
.. note:: Only the :ref:`MEMFS <filesystem-api-memfs>` filesystem is included by default. All others must be enabled explicitly, using ``-lnodefs.js`` (:ref:`NODEFS <filesystem-api-nodefs>`), ``-lidbfs.js`` (:ref:`IDBFS <filesystem-api-idbfs>`), ``-lfsfs.js`` (:ref:`FSFS <filesystem-api-fsfs>`), ``-lworkerfs.js`` (:ref:`WORKERFS <filesystem-api-workerfs>`), or ``-lproxyfs.js`` (:ref:`PROXYFS <filesystem-api-proxyfs>`). |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Note: I couldn't find any documentation on how to build and view these docs, so I haven't verified these changes.
|
||
The *FSFS* file system implements the :js:func:`FS.syncfs` interface, which when called will persist any operations to the attached ``FileSystemDirectoryHandle``. | ||
|
||
This uses the `File System Access API <https://web.dev/file-system-access/>`_, which is currently only supported by Chromium browsers. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
That's my understanding too...I'll verify and update the text.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yup, this works too. And it allows the test to run without any user interaction, which is great!
It definitely makes sense to support this browser API, but we are hoping to deprecate the old FS soon given the progress on WasmFS. Bugfixes are great there, of course, but for new backends it probably makes more sense in WasmFS, though things are not 100% stable there (but there is a PR for an OPFS backend, #16813). @tlively what do you think? |
You probably know this already, but just to be clear: There's a definite performance benefit to the synchronous FS API, but if you can't run that code in a worker for some reason then it isn't an option (I'm not 100% sure if my application could even make use of a worker version of the FS). That's the biggest difference between these two implementations, the other being not using the new WasmFS backend. I'm not familiar with WasmFS yet so maybe this is not a real problem. Oh, and this PR accepts any directory handle, while the one you shared just uses the private directory (I've commented on the PR about that, Any chance this could land, even if it's just around for a couple releases? Sounds like WasmFS is an unknown amount of time away from being stable... but if it's just a matter of days then yeah I don't see the point. Although I imagine the old FS code will stick around for X releases just in case? If not, no worries. I've got it working locally for my application, just figured it'd be good to upstream it. |
If this PR is urgent to land then I wouldn't oppose it, as it doesn't add much complexity or other risk. However, if this can wait say a few months then I'd recommend working on a WasmFS version for it instead.
Yes, even after we enable WasmFS by default I expect the old FS will stick around for a while. |
Not urgent for me. @tomayac are you aware of any emscripten users that would benefit from this today? This snippet should also serve as a drop-in library, it's basically what I'm using right now: https://gist.github.com/connorjclark/4707adbb5f2ea2322511b7e43942b10b Depending on when WasmFS is ready, I may not be readily available to work on the FS API backend, but I'll give it a shot if I've got the time. Is there a good issue I can follow to know when it'd be time to try? |
@connorjclark, actually, it might be reasonable to try adding this support as soon as #16813 lands if you want to build the new functionality into that OPFS backend. |
I'm not totally certain how much/if any of that can be reused for the generic FS API given the usage of |
I think if you add a bool to |
Yeah, renaming + offering a way to pass in your own (non-sync) directory handle (and using the sync navigator.getDirectory() by default if not provided) might not be a bad way to combine all this into one backend. I'll experiment when you've landed it! |
I think a couple of folks would be pretty excited, but admittedly from the people I know @ RReverser (mention broken on purpose) is closer to the scene, but (i) has left Google and (ii) has other things on his mind at the moment. |
@connorjclark Because passing ArrayBufers to WORKERFS appears to involve copying or serializing of data on Android (not on Linux or Windows, where just the reference is passed), over at Kiwix we're looking for a way to work more directly with JavaScript File handles (whether the good old File API or the File System Access API). Would this code allow access to a 92GB file handle that has been picked by the user? I know the File System Access API file and directory pickers aren't supported on Android (Chromium), and they're not supported at all on Firefox (on any platform), but would this code work with File API as a fallback? I'll make a separate issue about our problems with WORKERFS on Android. It works great on other platforms, even with huge archives, but only works with small archives (probably less than system memory size) on Android, which is not supposed to happen. |
I don't currently plan on re-adapting this PR to use the other backened any time soon, so I'll close this. On the other hand, if it's decided this current implementation is ok as-is, I'm happy to rebaseline. I have a drop-in replacement for this patch available here, for anyone interested: https://github.com/ArmageddonGames/ZQuestClassic/blob/main/web/fsfs.js . If someone ends up using the above and finds issues or makes useful improvements, I'd be grateful if you upstreamed them to me (via the above repro would be more appropriate than in this PR thread - https://github.com/connorjclark/emscripten/tree/fsfs is also ok if more convenient). |
This patch adds a new filesystem interface
FSFS
which utilizes the new File System Access API. Like idb, this is an asynchronous API. The implementation is nearly 1:1 with the idb interface, with a few key differences:mode
is not supported. All files and folders are written to Emscripten's FS as 0777Closes #15277, #12428