Skip to content
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

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

Open
msabwat opened this issue May 5, 2021 · 3 comments
Open

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

msabwat opened this issue May 5, 2021 · 3 comments

Comments

@msabwat
Copy link
Contributor

msabwat commented May 5, 2021

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.

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 <input type="file"> 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 <html5.h>
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) And also handle directories, and file writes (and when it will be supported by other browsers).

issue to track

@sbc100
Copy link
Collaborator

sbc100 commented May 5, 2021

Sounds good to me. Starting with and API that run on the main thread sounds like the way to go. It could come in sync and async flavors (the sync flavor would require ASYNCIFY on the main thread of course).

When calling this APIs from a pthread we could then (just as we do for most other web APIs) proxy the calls back to the main thread).

In terms of API naming I would suggest a common prefix (e.g. emscripten_fs_access_XX) for all functions that are part of this new API.

@kripken
Copy link
Member

kripken commented May 7, 2021

Now we can add Module.fileHandle to the shared objects that can be posted to a pthread worker

What API would be used to post the object? (All I can think of is the initial postMessage during the worker creation, but I assume you don't mean that?)

@msabwat
Copy link
Contributor Author

msabwat commented May 7, 2021

Now we can add Module.fileHandle to the shared objects that can be posted to a pthread worker

What API would be used to post the object? (All I can think of is the initial postMessage during the worker creation, but I assume you don't mean that?)

I did mean that, but I am noticing it is not Transferable (I was serializing it), so it's a bad idea to postMessage() it, sorry. The API would be provided by emscripten :

  • if the read function is called from a pthread it could signal the main thread and have the bytes available in wasmMemory.buffer
  • if it is called in the main_thread it could use the usual FileReader() method.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants