feat(storageState): add OPFS support#41420
Conversation
6f6684c to
18b71cc
Compare
| } | ||
|
|
||
| // Getting a File object's contents requires async | ||
| export async function serializeFile(value: File): Promise<Extract<SerializedValue, { f: any; }>> { |
This comment was marked as outdated.
This comment was marked as outdated.
Sorry, something went wrong.
| }; | ||
|
|
||
| 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) { |
There was a problem hiding this comment.
I did it like this so that we would get File object support in IndexedDB as a side effect of the PR, but yeah it's not strictly necessary
|
|
||
| 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); |
e9d3564 to
2040049
Compare
|
i just realized, i don't think there's any way to set the lastModified or content type of the file when writing it into OPFS. Maybe we should just leave them out of the serialized data :/ Unfortunate cuz tests can't rely on these things (esp. the last modified date could be useful, i feel like) I mean, they have a solution: mocking FileSystemFileHandle#getFile i guess |
|
|
||
| async storageState(params: channels.APIRequestContextStorageStateParams, progress: Progress): Promise<channels.APIRequestContextStorageStateResult> { | ||
| return await this._object.storageState(progress, params.indexedDB); | ||
| return await this._object.storageState(progress, params.indexedDB, params.opfs); |
| }[], | ||
| }; | ||
|
|
||
| export type FSEntry = { |
There was a problem hiding this comment.
This file is generated, where did we get these entries from and why?
There was a problem hiding this comment.
oops, didn't know that
i didn't run the build or test my changes yet, thats why the PR is still a draft (i was waiting on a decision to move forward even with some stuff not being baseline widely available yet).
also, what do you think about the lastModified thing ? i think i'll just not store it: if we can't control it, might as well not make tests unreliable by making the serialization dependent on the current time
There was a problem hiding this comment.
found it, I edited packages/protocol/spec and docs/src.
| - `type` <[FSEntryType]<"file"|"folder">> Type of the entry. "folder" for the root of the OPFS | ||
| - `base64` ?<[string]> Contents of the file, for "file" entries | ||
| - `contentType` ?<[string]> Content type of the file, for "file" entries | ||
| - `entries` ?<[Array]<[Object]<[string], [any]>>> Array of child entries (recursive), for "folder" entries |
There was a problem hiding this comment.
The recursive nature of FSEntry is causing issues here (a type mismatch at APIRequest#newContext)
I think I'm gonna go with a flat structure instead, that store absolute paths to files. It's a bit annoying because we need to be able to represent empty directories so we still have to make base64 & contentType optional (or make them take sentinel values like application/vnd.playwright.opfs-folder for contentType but thats worse imo), but oh well.
08cbb44 to
bbaaff9
Compare
|
sorry for the big force-push, I forgot the conventional commits prefixes in my later commits (i mean it's gonna get squashed anyways i guess, but since contributing.md talks about naming your commits that way might aswell do it) |
There was a problem hiding this comment.
@pavelfeldman for the test, i'm planning on adding a "store TODOs to OPFS" button in the to-do-notifications mock app, that would write one folder per deadline month containing one .md file per item:
- list:
- listitem: "lorem [lorem] - 00:00, January 1 2027."
- listitem: "ipsum [ipsum] - 00:00, January 5 2027."
- listitem: "dolor [dolor] - 00:00, December 5 2027."would result in
(opfs root)
/ January
/ lorem.md
/ ipsum.md
/ December
/ dolor.md
is this okay?
Closes #41400