emscripten-core / emscripten-core/emscripten
[Feature] : file-system-access - get file handle in a pthread
- Dominant language
- C++
- Stars
- 27.6k
- Forks
- 3.6k
- Avg merge
- 1d 1h
- Merged PRs (30d)
- 105
Description
If no one planned to work on this feature, I would like to submit a PR (after adjustments and in accordance with the feedbacks in this ticket ofc).
In some projects, users may need to interact with the file-system picker to select a file, and make it available for processing in webassembly.
In a multithreaded application, (and if we want to do synchronous reads), we need to have the file handle available in the pthread worker.
There is a POC in the vlc.js application that uses this [patch](https://code.videolan.org/jbk/vlc.js/-/blob/wip.3/vlc_patches/emscripten-nativefs.patch).
I think it would be nice to have a shared handle holding the JS File instance, that is also available on pthread workers.
It could be done with a function in emscripten (triggered by user interaction), that opens a file picker, depending on if we are on chrome or not and sets the fileHandle (Module["fileHandle"]).
```
if (ENVIRONMENT_IS_WEB)
{
getElementById(ElementSetByUser).onclick = function() {
if (window.showOpenFilePicker !== undefined) {
Module.fileHandle = await window.showOpenFilePicker({
dict_from_enum(C_STRUCTS.EmscriptenFileHandleAttribute.accepted_file_types);
});
}
else {
getElementById("filepicker").change = function() {
Module.fileHandle = event.target.files[0];
// update C_STRUCTS.EmscriptenFileHandleAttribute
}
}
}
```
The click on ElementSetByUser will in both cases open the file picker. The user will need to add an indication in the UI, we don't need the `` element in chrome.
Now we can add Module.fileHandle to the shared objects that can be posted to a pthread worker, and receive it in src/worker.js :
```
if (e.data.fileHandle) {
if (typeof FileSystemFileHandle != "undefined") {
if (e.data.fileHandle instanceof FileSystemFileHandle) {
e.data.fileHandle.getFile().then((fileHandle) => {
Module["fileHandle"] = fileHandle;
});
}
}
if (e.data.fileHandle instanceof File) {
Module["fileHandle"] = e.data.fileHandle;
}
```
It would be exposed like emscripten_webgl_*()
```
// Init :
#include
EmscriptenFileHandleAttribute handle;
emscripten_init_fileHandle_attributes(&handle);
handle.file_system_access = 1; // supported (0 if we are not on chrome)
// accepted extensions or user defined one (mime type: list_of_extensions)
handle.accepted_file_types = FSA_TYPE_IMAGE; (or FSA_TYPE_VIDEO, or FSA_TYPE_LIST)
emscripten_create_fileHandle(ElementSetByUser, &handle);
// After this call Module["fileHandle"] has the selected File object, and handle has the attributes updated (name, size etc...)
// there is a click event associated with #element, that will call an internal function to open the file picker
```
The user interaction part can be removed when the file system access API will be supported in other browsers.
The next step could be to add functions that synchronously read/seek the file. (instead of [this](https://code.videolan.org/jbk/vlc.js/-/blob/wip.3/vlc_patches/0014-access-initial-emscripten-file-api-support.patch#L114)) And also handle directories, and file writes (and when it will be supported by other browsers).
[issue to track](https://github.com/mozilla/standards-positions/issues/154)
Contributor guide
Assessment
This issue has not been assessed yet.