Skip to content

Commit

Permalink
tidy up some stuff
Browse files Browse the repository at this point in the history
  • Loading branch information
jimmywarting committed Sep 27, 2021
1 parent 79a5dce commit bb8e331
Show file tree
Hide file tree
Showing 4 changed files with 131 additions and 86 deletions.
14 changes: 10 additions & 4 deletions src/adapters/indexeddb.js
Original file line number Diff line number Diff line change
Expand Up @@ -97,6 +97,8 @@ class Sink {
: reject(new DOMException(...GONE))
}
tx.oncomplete = () => resolve()
tx.onerror = reject
tx.onabort = reject
})
}
}
Expand All @@ -117,21 +119,24 @@ class FileHandle {
}

/** @param {FileHandle} other */
isSameEntry (other) {
async isSameEntry (other) {
return this._id === other._id
}

async getFile () {
/** @type {File} */
const file = await new Promise(resolve => {
store(this._db)[1].get(this._id).onsuccess = evt => resolve(evt.target.result)
const file = await new Promise((resolve, reject) => {
const req = store(this._db)[1].get(this._id)
req.onsuccess = evt => resolve(evt.target.result)
req.onerror = evt => reject(evt.target.error)
})
if (!file) throw new DOMException(...GONE)
return file
}

async createWritable (opts) {
const file = await this.getFile()
let file = await this.getFile() // Used directly to test existences
file = opts.keepExistingData ? file : new File([], this.name)
return new Sink(this._db, this._id, file.size, file)
}
}
Expand Down Expand Up @@ -179,6 +184,7 @@ class FolderHandle {
this.writable = true
}

/** @returns {AsyncGenerator<[string, FileHandle | FolderHandle]>} */
async * entries () {
const entries = await new Promise(resolve => {
store(this._db)[1].get(this._id).onsuccess = evt => resolve(evt.target.result)
Expand Down
72 changes: 41 additions & 31 deletions src/adapters/memory.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,13 +7,18 @@ const Blob = globalThis.Blob || await import('fetch-blob').then(m => m.Blob)
const { INVALID, GONE, MISMATCH, MOD_ERR, SYNTAX, SECURITY, DISALLOWED } = errors

export class Sink {
/** @param {FileHandle} fileHandle */
constructor (fileHandle) {

/**
* @param {FileHandle} fileHandle
* @param {File} file
*/
constructor (fileHandle, file) {
this.fileHandle = fileHandle
this.file = fileHandle.file
this.size = fileHandle.file.size
this.file = file
this.size = file.size
this.position = 0
}

write (chunk) {
let file = this.file

Expand Down Expand Up @@ -86,8 +91,8 @@ export class Sink {
this.file = blob
}
close () {
if (this.fileHandle.deleted) throw new DOMException(...GONE)
this.fileHandle.file = this.file
if (this.fileHandle._deleted) throw new DOMException(...GONE)
this.fileHandle._file = this.file
this.file =
this.position =
this.size = null
Expand All @@ -99,32 +104,37 @@ export class Sink {

export class FileHandle {
constructor (name = '', file = new File([], name), writable = true) {
this.file = file
this._file = file
this.name = name
this.kind = 'file'
this.deleted = false
this._deleted = false
this.writable = writable
this.readable = true
}

getFile () {
if (this.deleted) throw new DOMException(...GONE)
return this.file
async getFile () {
if (this._deleted) throw new DOMException(...GONE)
return this._file
}

createWritable (opts) {
async createWritable (opts) {
if (!this.writable) throw new DOMException(...DISALLOWED)
if (this.deleted) throw new DOMException(...GONE)
return new Sink(this)
if (this._deleted) throw new DOMException(...GONE)

const file = opts.keepExistingData
? await this.getFile()
: new File([], this.name)

return new Sink(this, file)
}

isSameEntry (other) {
async isSameEntry (other) {
return this === other
}

destroy () {
this.deleted = true
this.file = null
async _destroy () {
this._deleted = true
this._file = null
}
}

Expand All @@ -134,29 +144,29 @@ export class FolderHandle {
constructor (name, writable = true) {
this.name = name
this.kind = 'directory'
this.deleted = false
this._deleted = false
/** @type {Object.<string, (FolderHandle|FileHandle)>} */
this._entries = {}
this.writable = writable
this.readable = true
}

/** @returns {AsyncGenerator<[string, FileHandle | FolderHandle]>} */
async * entries () {
if (this.deleted) throw new DOMException(...GONE)
if (this._deleted) throw new DOMException(...GONE)
yield* Object.entries(this._entries)
}

isSameEntry (other) {
async isSameEntry (other) {
return this === other
}


/**
* @param {string} name
* @param {{ create: boolean; }} opts
*/
getDirectoryHandle (name, opts) {
if (this.deleted) throw new DOMException(...GONE)
async getDirectoryHandle (name, opts) {
if (this._deleted) throw new DOMException(...GONE)
const entry = this._entries[name]
if (entry) { // entry exist
if (entry instanceof FileHandle) {
Expand All @@ -177,7 +187,7 @@ export class FolderHandle {
* @param {string} name
* @param {{ create: boolean; }} opts
*/
getFileHandle (name, opts) {
async getFileHandle (name, opts) {
const entry = this._entries[name]
const isFile = entry instanceof FileHandle
if (entry && isFile) return entry
Expand All @@ -188,23 +198,23 @@ export class FolderHandle {
}
}

removeEntry (name, opts) {
async removeEntry (name, opts) {
const entry = this._entries[name]
if (!entry) throw new DOMException(...GONE)
entry.destroy(opts.recursive)
await entry._destroy(opts.recursive)
delete this._entries[name]
}

destroy (recursive) {
async _destroy (recursive) {
for (let x of Object.values(this._entries)) {
if (!recursive) throw new DOMException(...MOD_ERR)
x.destroy(recursive)
await x._destroy(recursive)
}
this._entries = {}
this.deleted = true
this._deleted = true
}
}

const fs = new FolderHandle('')

export default opts => fs
export default () => fs
64 changes: 36 additions & 28 deletions src/adapters/node.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,46 +9,53 @@ import { errors } from '../util.js'
const { INVALID, GONE, MISMATCH, MOD_ERR, SYNTAX } = errors

export class Sink {

/**
* @param {fs.FileHandle} fileHandle
* @param {number} size
*/
constructor (fileHandle, size) {
this.fileHandle = fileHandle
this.size = size
this.position = 0
this._fileHandle = fileHandle
this._size = size
this._position = 0
}

async abort() {
await this.fileHandle.close()
await this._fileHandle.close()
}

async write (chunk) {
if (typeof chunk === 'object') {
if (chunk.type === 'write') {
if (Number.isInteger(chunk.position) && chunk.position >= 0) {
this.position = chunk.position
this._position = chunk.position
}
if (!('data' in chunk)) {
await this.fileHandle.close()
await this._fileHandle.close()
throw new DOMException(...SYNTAX('write requires a data argument'))
}
chunk = chunk.data
} else if (chunk.type === 'seek') {
if (Number.isInteger(chunk.position) && chunk.position >= 0) {
if (this.size < chunk.position) {
if (this._size < chunk.position) {
throw new DOMException(...INVALID)
}
this.position = chunk.position
this._position = chunk.position
return
} else {
await this.fileHandle.close()
await this._fileHandle.close()
throw new DOMException(...SYNTAX('seek requires a position argument'))
}
} else if (chunk.type === 'truncate') {
if (Number.isInteger(chunk.size) && chunk.size >= 0) {
await this.fileHandle.truncate(chunk.size)
this.size = chunk.size
if (this.position > this.size) {
this.position = this.size
await this._fileHandle.truncate(chunk.size)
this._size = chunk.size
if (this._position > this._size) {
this._position = this._size
}
return
} else {
await this.fileHandle.close()
await this._fileHandle.close()
throw new DOMException(...SYNTAX('truncate requires a size argument'))
}
}
Expand All @@ -60,25 +67,25 @@ export class Sink {
chunk = Buffer.from(chunk)
} else if (chunk instanceof Blob) {
for await (const data of chunk.stream()) {
const res = await this.fileHandle.writev([data], this.position)
this.position += res.bytesWritten
this.size += res.bytesWritten
const res = await this._fileHandle.writev([data], this._position)
this._position += res.bytesWritten
this._size += res.bytesWritten
}
return
}

const res = await this.fileHandle.writev([chunk], this.position)
this.position += res.bytesWritten
this.size += res.bytesWritten
const res = await this._fileHandle.writev([chunk], this._position)
this._position += res.bytesWritten
this._size += res.bytesWritten
}

async close () {
await this.fileHandle.close()
// First make sure we close the handle
await this._fileHandle.close()
}
}

export class FileHandle {
_path

/**
* @param {string} path
Expand All @@ -97,11 +104,11 @@ export class FileHandle {
return fileFrom(this._path)
}

isSameEntry (other) {
return this._path === this.#getPath.apply(other)
async isSameEntry (other) {
return this._path === this._getPath.apply(other)
}

#getPath() {
_getPath() {
return this._path
}

Expand All @@ -118,17 +125,18 @@ export class FileHandle {
export class FolderHandle {
_path = ''

/** @param {string} path */
constructor (path, name = '') {
constructor (path = '', name = '') {
this.name = name
this.kind = 'directory'
this._path = path
}

isSameEntry (other) {
/** @param {FolderHandle} other */
async isSameEntry (other) {
return this._path === other._path
}

/** @returns {AsyncGenerator<[string, FileHandle | FolderHandle]>} */
async * entries () {
const dir = this._path
const items = await fs.readdir(dir).catch(err => {
Expand Down
Loading

0 comments on commit bb8e331

Please sign in to comment.