Bug 250495 - Data written via FileSystemSyncAccessHandle disappears after creating new FileSystemFileHandle
Summary: Data written via FileSystemSyncAccessHandle disappears after creating new Fil...
Status: RESOLVED FIXED
Alias: None
Product: WebKit
Classification: Unclassified
Component: Website Storage (show other bugs)
Version: Safari 16
Hardware: All Unspecified
: P2 Normal
Assignee: Sihui Liu
URL:
Keywords: BrowserCompat, InRadar
Depends on:
Blocks:
 
Reported: 2023-01-11 19:57 PST by Alex Titarenko
Modified: 2023-01-13 09:29 PST (History)
3 users (show)

See Also:


Attachments

Note You need to log in before you can comment on or make changes to this bug.
Description Alex Titarenko 2023-01-11 19:57:04 PST
With many attempts, I could not find a way to persist written data to FileSystemSyncAccessHandle.
The example from https://webkit.org/blog/12257/the-file-system-access-api-with-origin-private-file-system/ article works only if you try to getFile/read data from the same instance of FileSystemFileHandle, when you get a new instance of FileHandle all data disappears.

This can be easily reproduced with a slight modification to the existing LayoutTest at: https://github.com/WebKit/WebKit/blob/3729059e6a040c8c168679975c9d04dab48e5a4d/LayoutTests/storage/filesystemaccess/resources/file-handle-getfile.js#L44

If before `fileObject = await fileHandle.getFile();` line you place `fileHandle = await rootHandle.getFileHandle("file-handle-getfile.txt", { "create" : false });` you will not get any actual data in return, even if you add accessHandle.flush() call before accessHandle.close();

This works perfectly fine in Chrome but not in WebKit.

FileSystemSyncAccessHandle is the only available way to write data in WebKit but it's not working because it does not persist data.
Comment 1 Alex Titarenko 2023-01-11 20:22:13 PST
More clear information on how to reproduce:

In file:
https://github.com/WebKit/WebKit/blob/main/LayoutTests/storage/filesystemaccess/resources/file-handle-getfile.js

replace test function with:

```
async function test() 
{
    try {
        var rootHandle = await navigator.storage.getDirectory();
        // Create a new file for this test.
        await rootHandle.removeEntry("file-handle-getfile.txt").then(() => { }, () => { });
        fileHandle = await rootHandle.getFileHandle("file-handle-getfile.txt", { "create" : true });
        fileContent = "";
    
        // Write file content in worker.
        if (typeof WorkerGlobalScope !== 'undefined' && self instanceof WorkerGlobalScope) {
            console.log('hello from WebWorker')
            accessHandle = await fileHandle.createSyncAccessHandle();
            const encoder = new TextEncoder();
            fileContent = "This is a test.";
            writeBuffer = encoder.encode(fileContent);
            writeSize = accessHandle.write(writeBuffer, { "at" : 0 });
            shouldBe("writeSize", "writeBuffer.byteLength");
            accessHandle.flush(); // This is a new line
            accessHandle.close();
        }

        fileHandle = await rootHandle.getFileHandle("file-handle-getfile.txt"); // This is a new line
        fileObject = await fileHandle.getFile();
        readText = await read(fileObject);
        shouldBe("readText", "fileContent");

        finishTest();
    } catch (error) {
        finishTest(error.toString());
    }
}
```

Then run LayoutTest:
https://github.com/WebKit/WebKit/blob/main/LayoutTests/storage/filesystemaccess/file-handle-getfile-worker.html
Comment 2 Sihui Liu 2023-01-12 11:26:36 PST Comment hidden (obsolete)
Comment 3 Sihui Liu 2023-01-12 11:28:12 PST
(In reply to Alex Titarenko from comment #1)
> More clear information on how to reproduce:
> 
> In file:
> https://github.com/WebKit/WebKit/blob/main/LayoutTests/storage/
> filesystemaccess/resources/file-handle-getfile.js
> 
> replace test function with:
> 
> ```
> async function test() 
> {
>     try {
>         var rootHandle = await navigator.storage.getDirectory();
>         // Create a new file for this test.
>         await rootHandle.removeEntry("file-handle-getfile.txt").then(() => {
> }, () => { });
>         fileHandle = await
> rootHandle.getFileHandle("file-handle-getfile.txt", { "create" : true });
>         fileContent = "";
>     
>         // Write file content in worker.
>         if (typeof WorkerGlobalScope !== 'undefined' && self instanceof
> WorkerGlobalScope) {
>             console.log('hello from WebWorker')
>             accessHandle = await fileHandle.createSyncAccessHandle();
>             const encoder = new TextEncoder();
>             fileContent = "This is a test.";
>             writeBuffer = encoder.encode(fileContent);
>             writeSize = accessHandle.write(writeBuffer, { "at" : 0 });
>             shouldBe("writeSize", "writeBuffer.byteLength");
>             accessHandle.flush(); // This is a new line
>             accessHandle.close();
>         }
> 
>         fileHandle = await
> rootHandle.getFileHandle("file-handle-getfile.txt"); // This is a new line
>         fileObject = await fileHandle.getFile();
>         readText = await read(fileObject);
>         shouldBe("readText", "fileContent");
> 
>         finishTest();
>     } catch (error) {
>         finishTest(error.toString());
>     }
> }
> ```
> 
> Then run LayoutTest:
> https://github.com/WebKit/WebKit/blob/main/LayoutTests/storage/
> filesystemaccess/file-handle-getfile-worker.html

Thanks for the report. I think it's caused by file being truncated unexpectedly on FileSystemHandle creation. Will make a fix.
Comment 4 Radar WebKit Bug Importer 2023-01-12 11:29:25 PST
<rdar://problem/104187327>
Comment 5 Sihui Liu 2023-01-12 11:32:28 PST
Pull request: https://github.com/WebKit/WebKit/pull/8586
Comment 6 EWS 2023-01-13 09:29:48 PST
Committed 258876@main (60a6090b4106): <https://commits.webkit.org/258876@main>

Reviewed commits have been landed. Closing PR #8586 and removing active labels.