feat(storageState): add OPFS support#41420
Conversation
6f6684c to
18b71cc
Compare
| for (const [name, entry] of tree) { | ||
| if (!Array.isArray(entry)) { | ||
| const handle = await base.getFileHandle(name, { create: true }); | ||
| const writable = await handle.createWritable(); |
There was a problem hiding this comment.
FileSystemFileHandle#createWritable is only Baseline 2025... but the alternative (createSyncAccessHandle()) only works inside Web Workers...
is the storageScript running in a worker or not? if it isn't we might wanna document that this won't work on older browsers.
afaik there's no other way to write to OPFS unfortunately
There was a problem hiding this comment.
I don't see how this will work in Firefox: https://developer.mozilla.org/en-US/docs/Web/API/FileSystemFileHandle/createWritable
There was a problem hiding this comment.
it does work:
but it's only baseline 2025, that's what I was saying. The aternative is createSyncAccessHandle, but it needs to run in web workers so i was wondering if the storage script
- already runs in a web worker
- would be feasible to move into a web worker
- or feasible to move just the opfs handling in a web worker
- or if baseline 2025 is acceptable, as this doesn't break anything else (we just have to document that the opfs option for (set)StorageState is only supported on baseline >=2025 browsers)
| type OPFSTree = Array< | ||
| [name: string, contents: Extract<SerializedValue, {f: any}> | OPFSTree] | ||
| >; | ||
|
|
There was a problem hiding this comment.
not a Record (object) cuz otherwise differenciation between leaves and branches (files and directories) wouldnt be as easy
| } | ||
|
|
||
| // Getting a File object's contents requires async | ||
| export async function serializeFile(value: File): Promise<Extract<SerializedValue, { f: any; }>> { |
There was a problem hiding this comment.
this is kinda ugly but I don't see any other way to do it, except making serialzeAsCallArgument async which would be a whole other can of worms
| for (const [name, entry] of tree) { | ||
| if (!Array.isArray(entry)) { | ||
| const handle = await base.getFileHandle(name, { create: true }); | ||
| const writable = await handle.createWritable(); |
There was a problem hiding this comment.
I don't see how this will work in Firefox: https://developer.mozilla.org/en-US/docs/Web/API/FileSystemFileHandle/createWritable
| }; | ||
|
|
||
| type OPFSTree = Array< | ||
| [name: string, contents: Extract<SerializedValue, {f: any}> | OPFSTree] |
There was a problem hiding this comment.
Let's use conservative types:
type FSEntry {
type: 'file' | 'folder';
name: string;
lastModified: number;
}
type File = FSEntry & {
type: 'file';
base64: string;
}
type Folder = FSEntry & {
type: 'folder';
entries: (File | Folder)[];
}| { ta: { b: string, k: TypedArrayKind } } | | ||
| { ab: { b: string } }; | ||
| { ab: { b: string } } | | ||
| { f: { b: string, n: string, t: string, m: number } }; |
There was a problem hiding this comment.
You should be able to serialize and restore opfs without this.
| return base64ToTypedArray(value.ta.b, typedArrayConstructors[value.ta.k]); | ||
| if ('ab' in value) | ||
| return base64ToTypedArray(value.ab.b, Uint8Array).buffer; | ||
| if ('f' in value) { |
|
|
||
| async storageState(params: channels.BrowserContextStorageStateParams, progress: Progress): Promise<channels.BrowserContextStorageStateResult> { | ||
| return await this._context.storageState(progress, params.indexedDB, params.credentials); | ||
| return await this._context.storageState(progress, params.indexedDB, params.credentials, params.opfs); |
Closes #41400