Improve attachment memory safety, downloads, and high-memory alert UX.
All checks were successful
Queue Release Build / prepare (push) Successful in 20s
Deploy Web Apps / deploy (push) Successful in 9m2s
Queue Release Build / build-windows (push) Successful in 28m8s
Queue Release Build / build-linux (push) Successful in 47m26s
Queue Release Build / build-android (push) Successful in 19m52s
Queue Release Build / finalize (push) Successful in 4m42s
All checks were successful
Queue Release Build / prepare (push) Successful in 20s
Deploy Web Apps / deploy (push) Successful in 9m2s
Queue Release Build / build-windows (push) Successful in 28m8s
Queue Release Build / build-linux (push) Successful in 47m26s
Queue Release Build / build-android (push) Successful in 19m52s
Queue Release Build / finalize (push) Successful in 4m42s
Stream large receives to disk with chunk acks to cap renderer RAM, evict off-screen display blobs, and route exports through a disk-aware download service. Fix the high-memory dialog (backdrop dismiss, copy, log actions), allow diagnostics paths in the path jail, and restore persisted image hydration after reload. Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
@@ -68,6 +68,7 @@ import {
|
||||
grantPluginReadRoot,
|
||||
resolveReadablePath
|
||||
} from '../path-jail';
|
||||
import { isReadableRegularFile } from './file-read.rules';
|
||||
|
||||
const DEFAULT_MIME_TYPE = 'application/octet-stream';
|
||||
const MAX_ACTIVE_DESKTOP_NOTIFICATIONS = 20;
|
||||
@@ -654,9 +655,19 @@ export function setupSystemHandlers(): void {
|
||||
return null;
|
||||
}
|
||||
|
||||
const data = await fsp.readFile(scopedPath);
|
||||
try {
|
||||
const stats = await fsp.stat(scopedPath);
|
||||
|
||||
return data.toString('base64');
|
||||
if (!isReadableRegularFile(stats)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
const data = await fsp.readFile(scopedPath);
|
||||
|
||||
return data.toString('base64');
|
||||
} catch {
|
||||
return null;
|
||||
}
|
||||
});
|
||||
|
||||
ipcMain.handle('read-file-chunk', async (_event, filePath: string, start: number, end: number) => {
|
||||
@@ -666,17 +677,27 @@ export function setupSystemHandlers(): void {
|
||||
return null;
|
||||
}
|
||||
|
||||
const fileHandle = await fsp.open(scopedPath, 'r');
|
||||
|
||||
try {
|
||||
const safeStart = Math.max(0, Math.trunc(start));
|
||||
const safeEnd = Math.max(safeStart, Math.trunc(end));
|
||||
const buffer = Buffer.alloc(safeEnd - safeStart);
|
||||
const result = await fileHandle.read(buffer, 0, buffer.length, safeStart);
|
||||
const stats = await fsp.stat(scopedPath);
|
||||
|
||||
return buffer.subarray(0, result.bytesRead).toString('base64');
|
||||
} finally {
|
||||
await fileHandle.close();
|
||||
if (!isReadableRegularFile(stats)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
const fileHandle = await fsp.open(scopedPath, 'r');
|
||||
|
||||
try {
|
||||
const safeStart = Math.max(0, Math.trunc(start));
|
||||
const safeEnd = Math.max(safeStart, Math.trunc(end));
|
||||
const buffer = Buffer.alloc(safeEnd - safeStart);
|
||||
const result = await fileHandle.read(buffer, 0, buffer.length, safeStart);
|
||||
|
||||
return buffer.subarray(0, result.bytesRead).toString('base64');
|
||||
} finally {
|
||||
await fileHandle.close();
|
||||
}
|
||||
} catch {
|
||||
return null;
|
||||
}
|
||||
});
|
||||
|
||||
@@ -728,6 +749,17 @@ export function setupSystemHandlers(): void {
|
||||
return true;
|
||||
});
|
||||
|
||||
ipcMain.handle('append-file-bytes', async (_event, filePath: string, bytes: Uint8Array) => {
|
||||
const scopedPath = await resolveWritableUserDataFilePath(filePath);
|
||||
|
||||
if (!scopedPath) {
|
||||
return false;
|
||||
}
|
||||
|
||||
await fsp.appendFile(scopedPath, Buffer.from(bytes));
|
||||
return true;
|
||||
});
|
||||
|
||||
ipcMain.handle('delete-file', async (_event, filePath: string) => {
|
||||
const scopedPath = await resolveWritableUserDataFilePath(filePath);
|
||||
|
||||
|
||||
Reference in New Issue
Block a user