emscripten-core / emscripten-core/emscripten

[Feature] : file-system-access - get file handle in a pthread

Open
#14,094 3 comments 0 reactions 0 assignees View on GitHub
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

Open the contributing guide

Assessment

This issue has not been assessed yet.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.