Muffin 2024-08-01 00:29:54 -05:00
parent fd00f12e9f
commit e0097f1b50
5 changed files with 27 additions and 13 deletions

3
package-lock.json generated
View File

@ -12440,8 +12440,9 @@
},
"node_modules/scratch-gui": {
"version": "3.2.37",
"resolved": "git+ssh://git@github.com/TurboWarp/scratch-gui.git#9a589c06cdc99841e0f98b1d629d292aa0016ab0",
"resolved": "git+ssh://git@github.com/TurboWarp/scratch-gui.git#457b36f20b30744656a8956f3eb0b0dc7c30365e",
"dev": true,
"license": "GPL-3.0",
"dependencies": {
"@microbit/microbit-universal-hex": "0.2.2",
"@turbowarp/nanolog": "^0.2.0",

View File

@ -11,7 +11,7 @@ import {
requestNewProject
} from 'scratch-gui/src/reducers/project-state';
import {setFileHandle, setUsername} from 'scratch-gui/src/reducers/tw';
import {WrappedFileHandle} from './filesystem-api-impl';
import {WrappedFileHandle} from './filesystem-api.js';
import {setStrings} from '../prompt/prompt.js';
let mountedOnce = false;

View File

@ -1,6 +1,10 @@
/**
* Partial reimplementation of the FileSystem API
* https://web.dev/file-system-access/
* Partial reimplementation of the FileSystem API (https://web.dev/file-system-access/)
*
* Unlike the default FileSystem API, we can construct a file handle from an ID from
* the main process without showing the file picker. The IDs are managed by the main
* process, so malicious extensions can't abuse this to get arbitrary read/write,
* and it lets us not share full file paths which could contain eg. the user's name.
*/
/**
@ -100,7 +104,7 @@ class WrappedFileWritable {
}
}
export class WrappedFileHandle {
class WrappedFileHandle {
/**
* @param {number} id File ID from main.
* @param {string} name Name including file extension.
@ -127,7 +131,15 @@ class AbortError extends Error {
}
}
window.showSaveFilePicker = async (options) => {
const showOpenFilePicker = async () => {
const result = await EditorPreload.showOpenFilePicker();
if (result === null) {
throw new AbortError('No file selected');
}
return [new WrappedFileHandle(result.id, result.name)];
};
const showSaveFilePicker = async (options) => {
const result = await EditorPreload.showSaveFilePicker(options.suggestedName);
if (result === null) {
throw new AbortError('No file selected');
@ -135,10 +147,8 @@ window.showSaveFilePicker = async (options) => {
return new WrappedFileHandle(result.id, result.name);
};
window.showOpenFilePicker = async () => {
const result = await EditorPreload.showOpenFilePicker();
if (result === null) {
throw new AbortError('No file selected');
}
return [new WrappedFileHandle(result.id, result.name)];
export {
WrappedFileHandle,
showOpenFilePicker,
showSaveFilePicker
};

View File

@ -5,6 +5,7 @@ import GUI, {AppStateHOC} from 'scratch-gui';
import ErrorContainerHOC from '../error/error-container-hoc.jsx';
import DesktopHOC from './desktop-hoc.jsx';
import CloudProviderHOC from './cloud-provider-hoc.jsx';
import {showOpenFilePicker, showSaveFilePicker} from './filesystem-api.js';
import './normalize.css';
import './gui.css';
@ -28,6 +29,9 @@ const GUIWithProps = () => (
backpackVisible
backpackHost="_local_"
showOpenFilePicker={showOpenFilePicker}
showSaveFilePicker={showSaveFilePicker}
/>
);

View File

@ -2,7 +2,6 @@ import React from 'react';
import ReactDOM from 'react-dom';
import GUI from './gui.jsx';
import './filesystem-api-impl.js';
import './media-device-chooser-impl.js';
import '../prompt/prompt.js';