Skip to content

Commit df93aa0

Browse files
committed
fix: handle getFile returning null and close #106, close #120
1 parent 0df8e12 commit df93aa0

File tree

2 files changed

+44
-6
lines changed

2 files changed

+44
-6
lines changed

src/file-selector.spec.ts

Lines changed: 34 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -379,6 +379,37 @@ it("should not use getAsFileSystemHandle when not in a secure context", async ()
379379
globalThis.isSecureContext = true;
380380
});
381381

382+
it("should reject when getAsFileSystemHandle resolves to null", async () => {
383+
const evt = dragEvtFromItems([dataTransferItemWithFsHandle(null, null)]);
384+
expect(fromEvent(evt)).rejects.toThrow("[object Object] is not a File");
385+
});
386+
387+
it("should fallback to getAsFile when getAsFileSystemHandle resolves to undefined", async () => {
388+
const name = "test.nosec.json";
389+
const mockFile = createFile(
390+
name,
391+
{ ping: false },
392+
{
393+
type: "application/json",
394+
},
395+
);
396+
const evt = dragEvtFromItems([
397+
dataTransferItemWithFsHandle(mockFile, undefined),
398+
]);
399+
400+
const files = await fromEvent(evt);
401+
expect(files).toHaveLength(1);
402+
expect(files.every((file) => file instanceof File)).toBe(true);
403+
404+
const [file] = files as FileWithPath[];
405+
406+
expect(file.name).toBe(mockFile.name);
407+
expect(file.type).toBe(mockFile.type);
408+
expect(file.size).toBe(mockFile.size);
409+
expect(file.lastModified).toBe(mockFile.lastModified);
410+
expect(file.path).toBe(`./${name}`);
411+
});
412+
382413
function dragEvtFromItems(
383414
items: DataTransferItem | DataTransferItem[],
384415
type: string = "drop",
@@ -456,8 +487,8 @@ function dataTransferItemFromEntry(
456487
}
457488

458489
function dataTransferItemWithFsHandle(
459-
file?: File,
460-
h?: FileSystemFileHandle,
490+
file?: File | null,
491+
h?: FileSystemFileHandle | null,
461492
): DataTransferItem {
462493
return {
463494
kind: "file",
@@ -570,7 +601,7 @@ function sortFiles<T extends File>(files: T[]) {
570601
}
571602

572603
interface FileSystemFileHandle {
573-
getFile(): Promise<File>;
604+
getFile(): Promise<File | null>;
574605
}
575606

576607
type FileOrDirEntry = FileEntry | DirEntry;

src/file-selector.ts

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -119,9 +119,16 @@ async function fromDataTransferItem(
119119
typeof (item as any).getAsFileSystemHandle === "function"
120120
) {
121121
const h = await (item as any).getAsFileSystemHandle();
122-
const file = await h.getFile();
123-
file.handle = h;
124-
return toFileWithPath(file);
122+
if (h === null) {
123+
throw new Error(`${item} is not a File`);
124+
}
125+
// It seems that the handle can be `undefined` (see https://github.com/react-dropzone/file-selector/issues/120),
126+
// so we check if it isn't; if it is, the code path continues to the next API (`getAsFile`).
127+
if (h !== undefined) {
128+
const file = await h.getFile();
129+
file.handle = h;
130+
return toFileWithPath(file);
131+
}
125132
}
126133
const file = item.getAsFile();
127134
if (!file) {

0 commit comments

Comments
 (0)