Skip to content

Commit

Permalink
fix: use window.FileList instead of implicit global
Browse files Browse the repository at this point in the history
  • Loading branch information
ph-fritsche committed Jul 15, 2022
1 parent c376fbc commit c88865d
Show file tree
Hide file tree
Showing 5 changed files with 67 additions and 56 deletions.
10 changes: 8 additions & 2 deletions src/utility/upload.ts
@@ -1,4 +1,10 @@
import {createFileList, isDisabled, isElementType, setFiles} from '../utils'
import {
createFileList,
getWindow,
isDisabled,
isElementType,
setFiles,
} from '../utils'
import {Config, Instance} from '../setup'

export interface uploadInit {
Expand Down Expand Up @@ -36,7 +42,7 @@ export async function upload(
return
}

setFiles(input, createFileList(files))
setFiles(input, createFileList(getWindow(element), files))
this.dispatchUIEvent(input, 'input')
this.dispatchUIEvent(input, 'change')
}
Expand Down
94 changes: 48 additions & 46 deletions src/utils/dataTransfer/DataTransfer.ts
Expand Up @@ -74,63 +74,65 @@ function getTypeMatcher(type: string, exact: boolean) {
}
}

class DataTransferStub implements DataTransfer {
getData(format: string) {
const match =
this.items.find(getTypeMatcher(format, true)) ??
this.items.find(getTypeMatcher(format, false))

let text = ''
match?.getAsString(t => {
text = t
})

return text
}

setData(format: string, data: string) {
const matchIndex = this.items.findIndex(getTypeMatcher(format, true))

const item = new DataTransferItemStub(data, format) as DataTransferItem
if (matchIndex >= 0) {
this.items.splice(matchIndex, 1, item)
} else {
this.items.push(item)
function createDataTransferStub(window: Window & typeof globalThis) {
return new (class DataTransferStub implements DataTransfer {
getData(format: string) {
const match =
this.items.find(getTypeMatcher(format, true)) ??
this.items.find(getTypeMatcher(format, false))

let text = ''
match?.getAsString(t => {
text = t
})

return text
}
}

clearData(format?: string) {
if (format) {
setData(format: string, data: string) {
const matchIndex = this.items.findIndex(getTypeMatcher(format, true))

const item = new DataTransferItemStub(data, format) as DataTransferItem
if (matchIndex >= 0) {
this.items.remove(matchIndex)
this.items.splice(matchIndex, 1, item)
} else {
this.items.push(item)
}
} else {
this.items.clear()
}
}

dropEffect: DataTransfer['dropEffect'] = 'none'
effectAllowed: DataTransfer['effectAllowed'] = 'uninitialized'

readonly items = new DataTransferItemListStub()
readonly files = createFileList([])
clearData(format?: string) {
if (format) {
const matchIndex = this.items.findIndex(getTypeMatcher(format, true))

get types() {
const t = []
if (this.files.length) {
t.push('Files')
if (matchIndex >= 0) {
this.items.remove(matchIndex)
}
} else {
this.items.clear()
}
}
this.items.forEach(i => t.push(i.type))

Object.freeze(t)
dropEffect: DataTransfer['dropEffect'] = 'none'
effectAllowed: DataTransfer['effectAllowed'] = 'uninitialized'

return t
}
readonly items = new DataTransferItemListStub()
readonly files = createFileList(window, [])

/* istanbul ignore next */
setDragImage() {}
get types() {
const t = []
if (this.files.length) {
t.push('Files')
}
this.items.forEach(i => t.push(i.type))

Object.freeze(t)

return t
}

/* istanbul ignore next */
setDragImage() {}
})()
}

export function createDataTransfer(
Expand All @@ -140,10 +142,10 @@ export function createDataTransfer(
// Use real DataTransfer if available
const dt =
typeof window.DataTransfer === 'undefined'
? (new DataTransferStub() as DataTransfer)
? createDataTransferStub(window)
: /* istanbul ignore next */ new window.DataTransfer()

Object.defineProperty(dt, 'files', {get: () => createFileList(files)})
Object.defineProperty(dt, 'files', {get: () => createFileList(window, files)})

return dt
}
Expand Down
9 changes: 6 additions & 3 deletions src/utils/dataTransfer/FileList.ts
@@ -1,6 +1,9 @@
// FileList can not be created per constructor.

export function createFileList(files: File[]): FileList {
export function createFileList(
window: Window & typeof globalThis,
files: File[],
): FileList {
const list: FileList & Iterable<File> = {
...files,
length: files.length,
Expand All @@ -11,8 +14,8 @@ export function createFileList(files: File[]): FileList {
}
},
}
list.constructor = FileList
Object.setPrototypeOf(list, FileList.prototype)
list.constructor = window.FileList
Object.setPrototypeOf(list, window.FileList.prototype)
Object.freeze(list)

return list
Expand Down
2 changes: 1 addition & 1 deletion tests/utils/dataTransfer/FileList.ts
Expand Up @@ -2,7 +2,7 @@ import {createFileList} from '#src/utils'

test('implement FileList', () => {
const file = new File(['hello'], 'hello.png', {type: 'image/png'})
const list = createFileList([file])
const list = createFileList(window, [file])

expect(list).toBeInstanceOf(FileList)
expect(list).toHaveLength(1)
Expand Down
8 changes: 4 additions & 4 deletions tests/utils/edit/setFiles.ts
Expand Up @@ -6,7 +6,7 @@ test('set files', () => {
`<input type="file"/>`,
)

const list = createFileList([new File(['foo'], 'foo.txt')])
const list = createFileList(window, [new File(['foo'], 'foo.txt')])
setFiles(element, list)

expect(element).toHaveProperty('files', list)
Expand All @@ -20,7 +20,7 @@ test('switching type resets value', () => {

expect(element).toHaveValue('')

const list = createFileList([new File(['foo'], 'foo.txt')])
const list = createFileList(window, [new File(['foo'], 'foo.txt')])
setFiles(element as HTMLInputElement & {type: 'file'}, list)

element.type = 'file'
Expand All @@ -38,7 +38,7 @@ test('setting value resets `files`', () => {
`<input type="file"/>`,
)

const list = createFileList([new File(['foo'], 'foo.txt')])
const list = createFileList(window, [new File(['foo'], 'foo.txt')])
setFiles(element, list)

// Everything but an empty string throws an error in the browser
Expand All @@ -58,7 +58,7 @@ test('is save to call multiple times', () => {
`<input type="file"/>`,
)

const list = createFileList([new File(['foo'], 'foo.txt')])
const list = createFileList(window, [new File(['foo'], 'foo.txt')])
setFiles(element, list)
setFiles(element, list)

Expand Down

0 comments on commit c88865d

Please sign in to comment.