Skip to content

Commit 5ec58b2

Browse files
committed
fix: use getAsFileSystemHandle only in secure ctx
1 parent f159a4a commit 5ec58b2

File tree

4 files changed

+47
-4
lines changed

4 files changed

+47
-4
lines changed

jest.config.js

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,9 @@
1-
/** @type {import('ts-jest').JestConfigWithTsJest} **/
1+
/** @type {import('ts-jest').ProjectConfigTsJest} **/
22
module.exports = {
33
testEnvironment: 'jsdom',
4+
"setupFilesAfterEnv": [
5+
"<rootDir>/test-setup.js"
6+
],
47
transform: {
58
'^.+.tsx?$': [
69
'ts-jest',

src/file-selector.spec.ts

Lines changed: 30 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -304,6 +304,35 @@ it('should use getAsFileSystemHandle when available', async () => {
304304
expect(file.path).toBe(`./${name}`);
305305
});
306306

307+
it('should not use getAsFileSystemHandle when not in a secure context', async () => {
308+
const f1Name = 'test.nosec.json';
309+
const f1 = createFile(f1Name, {ping: false}, {
310+
type: 'application/json'
311+
});
312+
const [_, h] = createFileSystemFileHandle('test.sec.json', {ping: true}, {
313+
type: 'application/json'
314+
});
315+
const evt = dragEvtFromItems([
316+
dataTransferItemWithFsHandle(f1, h)
317+
]);
318+
319+
window.isSecureContext = false;
320+
321+
const files = await fromEvent(evt);
322+
expect(files).toHaveLength(1);
323+
expect(files.every(file => file instanceof File)).toBe(true);
324+
325+
const [file] = files as FileWithPath[];
326+
327+
expect(file.name).toBe(f1.name);
328+
expect(file.type).toBe(f1.type);
329+
expect(file.size).toBe(f1.size);
330+
expect(file.lastModified).toBe(f1.lastModified);
331+
expect(file.path).toBe(`./${f1Name}`);
332+
333+
window.isSecureContext = true;
334+
});
335+
307336
function dragEvtFromItems(items: DataTransferItem | DataTransferItem[], type: string = 'drop'): DragEvent {
308337
return {
309338
type,
@@ -466,8 +495,7 @@ function createFile<T>(name: string, data: T, options?: FilePropertyBag) {
466495
}
467496

468497
function createFileSystemFileHandle<T>(name: string, data: T, options?: FilePropertyBag): [File, FileSystemFileHandle] {
469-
const json = JSON.stringify(data);
470-
const file = new File([json], name, options);
498+
const file = createFile(name, data, options);
471499
return [file, {
472500
getFile() {
473501
return Promise.resolve(file);

src/file-selector.ts

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -121,7 +121,13 @@ function flatten<T>(items: any[]): T[] {
121121
}
122122

123123
function fromDataTransferItem(item: DataTransferItem, entry?: FileSystemEntry | null) {
124-
if (typeof (item as any).getAsFileSystemHandle === 'function') {
124+
// Check if we're in a secure context; due to a bug in Chrome (as far as we know)
125+
// the browser crashes when calling this API (yet to be confirmed as a consistent behaviour).
126+
//
127+
// See:
128+
// - https://issues.chromium.org/issues/40186242
129+
// - https://github.com/react-dropzone/react-dropzone/issues/1397
130+
if (globalThis.isSecureContext && typeof (item as any).getAsFileSystemHandle === 'function') {
125131
return (item as any).getAsFileSystemHandle()
126132
.then(async (h: any) => {
127133
const file = await h.getFile();

test-setup.js

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
// NOTE: Let us test {isSecureContext}!
2+
Object.defineProperty(globalThis, "isSecureContext", {
3+
value: true,
4+
writable: true,
5+
enumerable: true,
6+
});

0 commit comments

Comments
 (0)