Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Add support for a persisted disk image
Add a mode where we persist the changes made to a chunked disk image in the origin private file system feature that is supported by modern browsers. They also support being able to get a synchronous file handle, which allows us to directly intercept read/write calls from the emulator with no complications. The persistence is handled as an overlay on top of the chunked data, we have a separate dirty chunks bitmask that stores which chunks have been modified. When we're about to read from a chunk, we first load it from the persisted disk. Similarly, when a change to a chunk is made, we mark it as dirty and write it to the persisted disk. This does mean that there is some write amplification (any change writes a whole 256K chunk), but in practice performance appears to be OK (the native file system cache kicks in presumably). Since the disk image is mostly empty, we stored it compressed in Git (to avoid having a large file). We also optimize empty chunks, so that we don't need to store a signature for them, or load them over the network. To feature detect if the browser supports the origin private file system and synchronous file handles, we need to create a temporary worker (FileSystemSyncAccessHandle is only ever defined in workers). We cache the result of this check in localStorage so that we don't need to do it too often. Currently disabled by default, but accessible via the custom instance dialog or the ?saved_hd=true query parameter Updates #152
- Loading branch information
Showing
21 changed files
with
416 additions
and
12 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Binary file not shown.
Git LFS file not shown
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,5 @@ | ||
const supported = | ||
typeof FileSystemFileHandle.prototype.createSyncAccessHandle === | ||
"function" && typeof FileSystemSyncAccessHandle === "function"; | ||
|
||
postMessage(supported); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,46 @@ | ||
import Worker from "./canSaveDisks-worker?worker&inline"; | ||
|
||
export function canSaveDisks() { | ||
if (!navigator.storage?.getDirectory) { | ||
return false; | ||
} | ||
if (typeof FileSystemFileHandle !== "function") { | ||
return false; | ||
} | ||
|
||
if (workerSyncFileSupport !== "unknown") { | ||
return workerSyncFileSupport === "supported"; | ||
} | ||
function update(support: "supported" | "unsupported") { | ||
if (workerSyncFileSupport === "unsupported") { | ||
// Ignore updates if one mechanism determined that it's unsupported. | ||
return; | ||
} | ||
workerSyncFileSupport = support; | ||
localStorage["workerSyncFileSupport"] = support; | ||
} | ||
|
||
// We can't check for the presence of FileSystemSyncAccessHandle in the | ||
// main window, it's only available in workers. So we have to create a | ||
// temporary one to check, but we cache the result in localStorage so that | ||
// we can avoid doing this every time. | ||
if (!worker) { | ||
worker = new Worker(); | ||
worker.addEventListener("message", e => { | ||
update(e.data ? "supported" : "unsupported"); | ||
worker?.terminate(); | ||
}); | ||
} | ||
|
||
// In private contexts Safari exposes the storage API, but calls to it will | ||
// fail, check for that too. | ||
navigator.storage.getDirectory().catch(() => update("unsupported")); | ||
|
||
// Assume supported until we hear otherwise. | ||
return true; | ||
} | ||
|
||
let workerSyncFileSupport: "unknown" | "supported" | "unsupported" = | ||
localStorage["workerSyncFileSupport"] ?? "unknown"; | ||
|
||
let worker: Worker | undefined; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.