345 lines
8.3 KiB
JavaScript
345 lines
8.3 KiB
JavaScript
'use strict'
|
||
|
||
const {
|
||
staticPropertyDescriptors,
|
||
readOperation,
|
||
fireAProgressEvent
|
||
} = require('./util')
|
||
const {
|
||
kState,
|
||
kError,
|
||
kResult,
|
||
kEvents,
|
||
kAborted
|
||
} = require('./symbols')
|
||
const { webidl } = require('../fetch/webidl')
|
||
const { kEnumerableProperty } = require('../core/util')
|
||
|
||
class FileReader extends EventTarget {
|
||
constructor () {
|
||
super()
|
||
|
||
this[kState] = 'empty'
|
||
this[kResult] = null
|
||
this[kError] = null
|
||
this[kEvents] = {
|
||
loadend: null,
|
||
error: null,
|
||
abort: null,
|
||
load: null,
|
||
progress: null,
|
||
loadstart: null
|
||
}
|
||
}
|
||
|
||
/**
|
||
* @see https://w3c.github.io/FileAPI/#dfn-readAsArrayBuffer
|
||
* @param {import('buffer').Blob} blob
|
||
*/
|
||
readAsArrayBuffer (blob) {
|
||
webidl.brandCheck(this, FileReader)
|
||
|
||
webidl.argumentLengthCheck(arguments, 1, { header: 'FileReader.readAsArrayBuffer' })
|
||
|
||
blob = webidl.converters.Blob(blob, { strict: false })
|
||
|
||
// The readAsArrayBuffer(blob) method, when invoked,
|
||
// must initiate a read operation for blob with ArrayBuffer.
|
||
readOperation(this, blob, 'ArrayBuffer')
|
||
}
|
||
|
||
/**
|
||
* @see https://w3c.github.io/FileAPI/#readAsBinaryString
|
||
* @param {import('buffer').Blob} blob
|
||
*/
|
||
readAsBinaryString (blob) {
|
||
webidl.brandCheck(this, FileReader)
|
||
|
||
webidl.argumentLengthCheck(arguments, 1, { header: 'FileReader.readAsBinaryString' })
|
||
|
||
blob = webidl.converters.Blob(blob, { strict: false })
|
||
|
||
// The readAsBinaryString(blob) method, when invoked,
|
||
// must initiate a read operation for blob with BinaryString.
|
||
readOperation(this, blob, 'BinaryString')
|
||
}
|
||
|
||
/**
|
||
* @see https://w3c.github.io/FileAPI/#readAsDataText
|
||
* @param {import('buffer').Blob} blob
|
||
* @param {string?} encoding
|
||
*/
|
||
readAsText (blob, encoding = undefined) {
|
||
webidl.brandCheck(this, FileReader)
|
||
|
||
webidl.argumentLengthCheck(arguments, 1, { header: 'FileReader.readAsText' })
|
||
|
||
blob = webidl.converters.Blob(blob, { strict: false })
|
||
|
||
if (encoding !== undefined) {
|
||
encoding = webidl.converters.DOMString(encoding)
|
||
}
|
||
|
||
// The readAsText(blob, encoding) method, when invoked,
|
||
// must initiate a read operation for blob with Text and encoding.
|
||
readOperation(this, blob, 'Text', encoding)
|
||
}
|
||
|
||
/**
|
||
* @see https://w3c.github.io/FileAPI/#dfn-readAsDataURL
|
||
* @param {import('buffer').Blob} blob
|
||
*/
|
||
readAsDataURL (blob) {
|
||
webidl.brandCheck(this, FileReader)
|
||
|
||
webidl.argumentLengthCheck(arguments, 1, { header: 'FileReader.readAsDataURL' })
|
||
|
||
blob = webidl.converters.Blob(blob, { strict: false })
|
||
|
||
// The readAsDataURL(blob) method, when invoked, must
|
||
// initiate a read operation for blob with DataURL.
|
||
readOperation(this, blob, 'DataURL')
|
||
}
|
||
|
||
/**
|
||
* @see https://w3c.github.io/FileAPI/#dfn-abort
|
||
*/
|
||
abort () {
|
||
// 1. If this's state is "empty" or if this's state is
|
||
// "done" set this's result to null and terminate
|
||
// this algorithm.
|
||
if (this[kState] === 'empty' || this[kState] === 'done') {
|
||
this[kResult] = null
|
||
return
|
||
}
|
||
|
||
// 2. If this's state is "loading" set this's state to
|
||
// "done" and set this's result to null.
|
||
if (this[kState] === 'loading') {
|
||
this[kState] = 'done'
|
||
this[kResult] = null
|
||
}
|
||
|
||
// 3. If there are any tasks from this on the file reading
|
||
// task source in an affiliated task queue, then remove
|
||
// those tasks from that task queue.
|
||
this[kAborted] = true
|
||
|
||
// 4. Terminate the algorithm for the read method being processed.
|
||
// TODO
|
||
|
||
// 5. Fire a progress event called abort at this.
|
||
fireAProgressEvent('abort', this)
|
||
|
||
// 6. If this's state is not "loading", fire a progress
|
||
// event called loadend at this.
|
||
if (this[kState] !== 'loading') {
|
||
fireAProgressEvent('loadend', this)
|
||
}
|
||
}
|
||
|
||
/**
|
||
* @see https://w3c.github.io/FileAPI/#dom-filereader-readystate
|
||
*/
|
||
get readyState () {
|
||
webidl.brandCheck(this, FileReader)
|
||
|
||
switch (this[kState]) {
|
||
case 'empty': return this.EMPTY
|
||
case 'loading': return this.LOADING
|
||
case 'done': return this.DONE
|
||
}
|
||
}
|
||
|
||
/**
|
||
* @see https://w3c.github.io/FileAPI/#dom-filereader-result
|
||
*/
|
||
get result () {
|
||
webidl.brandCheck(this, FileReader)
|
||
|
||
// The result attribute’s getter, when invoked, must return
|
||
// this's result.
|
||
return this[kResult]
|
||
}
|
||
|
||
/**
|
||
* @see https://w3c.github.io/FileAPI/#dom-filereader-error
|
||
*/
|
||
get error () {
|
||
webidl.brandCheck(this, FileReader)
|
||
|
||
// The error attribute’s getter, when invoked, must return
|
||
// this's error.
|
||
return this[kError]
|
||
}
|
||
|
||
get onloadend () {
|
||
webidl.brandCheck(this, FileReader)
|
||
|
||
return this[kEvents].loadend
|
||
}
|
||
|
||
set onloadend (fn) {
|
||
webidl.brandCheck(this, FileReader)
|
||
|
||
if (this[kEvents].loadend) {
|
||
this.removeEventListener('loadend', this[kEvents].loadend)
|
||
}
|
||
|
||
if (typeof fn === 'function') {
|
||
this[kEvents].loadend = fn
|
||
this.addEventListener('loadend', fn)
|
||
} else {
|
||
this[kEvents].loadend = null
|
||
}
|
||
}
|
||
|
||
get onerror () {
|
||
webidl.brandCheck(this, FileReader)
|
||
|
||
return this[kEvents].error
|
||
}
|
||
|
||
set onerror (fn) {
|
||
webidl.brandCheck(this, FileReader)
|
||
|
||
if (this[kEvents].error) {
|
||
this.removeEventListener('error', this[kEvents].error)
|
||
}
|
||
|
||
if (typeof fn === 'function') {
|
||
this[kEvents].error = fn
|
||
this.addEventListener('error', fn)
|
||
} else {
|
||
this[kEvents].error = null
|
||
}
|
||
}
|
||
|
||
get onloadstart () {
|
||
webidl.brandCheck(this, FileReader)
|
||
|
||
return this[kEvents].loadstart
|
||
}
|
||
|
||
set onloadstart (fn) {
|
||
webidl.brandCheck(this, FileReader)
|
||
|
||
if (this[kEvents].loadstart) {
|
||
this.removeEventListener('loadstart', this[kEvents].loadstart)
|
||
}
|
||
|
||
if (typeof fn === 'function') {
|
||
this[kEvents].loadstart = fn
|
||
this.addEventListener('loadstart', fn)
|
||
} else {
|
||
this[kEvents].loadstart = null
|
||
}
|
||
}
|
||
|
||
get onprogress () {
|
||
webidl.brandCheck(this, FileReader)
|
||
|
||
return this[kEvents].progress
|
||
}
|
||
|
||
set onprogress (fn) {
|
||
webidl.brandCheck(this, FileReader)
|
||
|
||
if (this[kEvents].progress) {
|
||
this.removeEventListener('progress', this[kEvents].progress)
|
||
}
|
||
|
||
if (typeof fn === 'function') {
|
||
this[kEvents].progress = fn
|
||
this.addEventListener('progress', fn)
|
||
} else {
|
||
this[kEvents].progress = null
|
||
}
|
||
}
|
||
|
||
get onload () {
|
||
webidl.brandCheck(this, FileReader)
|
||
|
||
return this[kEvents].load
|
||
}
|
||
|
||
set onload (fn) {
|
||
webidl.brandCheck(this, FileReader)
|
||
|
||
if (this[kEvents].load) {
|
||
this.removeEventListener('load', this[kEvents].load)
|
||
}
|
||
|
||
if (typeof fn === 'function') {
|
||
this[kEvents].load = fn
|
||
this.addEventListener('load', fn)
|
||
} else {
|
||
this[kEvents].load = null
|
||
}
|
||
}
|
||
|
||
get onabort () {
|
||
webidl.brandCheck(this, FileReader)
|
||
|
||
return this[kEvents].abort
|
||
}
|
||
|
||
set onabort (fn) {
|
||
webidl.brandCheck(this, FileReader)
|
||
|
||
if (this[kEvents].abort) {
|
||
this.removeEventListener('abort', this[kEvents].abort)
|
||
}
|
||
|
||
if (typeof fn === 'function') {
|
||
this[kEvents].abort = fn
|
||
this.addEventListener('abort', fn)
|
||
} else {
|
||
this[kEvents].abort = null
|
||
}
|
||
}
|
||
}
|
||
|
||
// https://w3c.github.io/FileAPI/#dom-filereader-empty
|
||
FileReader.EMPTY = FileReader.prototype.EMPTY = 0
|
||
// https://w3c.github.io/FileAPI/#dom-filereader-loading
|
||
FileReader.LOADING = FileReader.prototype.LOADING = 1
|
||
// https://w3c.github.io/FileAPI/#dom-filereader-done
|
||
FileReader.DONE = FileReader.prototype.DONE = 2
|
||
|
||
Object.defineProperties(FileReader.prototype, {
|
||
EMPTY: staticPropertyDescriptors,
|
||
LOADING: staticPropertyDescriptors,
|
||
DONE: staticPropertyDescriptors,
|
||
readAsArrayBuffer: kEnumerableProperty,
|
||
readAsBinaryString: kEnumerableProperty,
|
||
readAsText: kEnumerableProperty,
|
||
readAsDataURL: kEnumerableProperty,
|
||
abort: kEnumerableProperty,
|
||
readyState: kEnumerableProperty,
|
||
result: kEnumerableProperty,
|
||
error: kEnumerableProperty,
|
||
onloadstart: kEnumerableProperty,
|
||
onprogress: kEnumerableProperty,
|
||
onload: kEnumerableProperty,
|
||
onabort: kEnumerableProperty,
|
||
onerror: kEnumerableProperty,
|
||
onloadend: kEnumerableProperty,
|
||
[Symbol.toStringTag]: {
|
||
value: 'FileReader',
|
||
writable: false,
|
||
enumerable: false,
|
||
configurable: true
|
||
}
|
||
})
|
||
|
||
Object.defineProperties(FileReader, {
|
||
EMPTY: staticPropertyDescriptors,
|
||
LOADING: staticPropertyDescriptors,
|
||
DONE: staticPropertyDescriptors
|
||
})
|
||
|
||
module.exports = {
|
||
FileReader
|
||
}
|