@zenfs/dom 1.1.6 → 1.1.7
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/IndexedDB.d.ts +12 -4
- package/dist/IndexedDB.js +32 -7
- package/dist/access.d.ts +2 -2
- package/dist/access.js +16 -15
- package/dist/devices/framebuffer.js +2 -2
- package/dist/storage.js +4 -3
- package/dist/utils.d.ts +3 -3
- package/dist/utils.js +5 -4
- package/dist/xml.js +10 -9
- package/package.json +4 -3
package/dist/IndexedDB.d.ts
CHANGED
|
@@ -1,24 +1,32 @@
|
|
|
1
1
|
import type { SharedConfig, Store } from '@zenfs/core';
|
|
2
|
-
import {
|
|
3
|
-
import type * as cache from 'utilium/cache.js';
|
|
2
|
+
import { StoreFS, Transaction } from '@zenfs/core';
|
|
4
3
|
/**
|
|
5
4
|
* @internal @hidden
|
|
6
5
|
*/
|
|
7
|
-
export declare class IndexedDBTransaction extends
|
|
6
|
+
export declare class IndexedDBTransaction extends Transaction<IndexedDBStore> {
|
|
8
7
|
tx: IDBTransaction;
|
|
9
8
|
store: IndexedDBStore;
|
|
10
9
|
private _idb;
|
|
10
|
+
protected asyncDone: Promise<unknown>;
|
|
11
|
+
/**
|
|
12
|
+
* Run a asynchronous operation from a sync context. Not magic and subject to (race) conditions.
|
|
13
|
+
* @internal
|
|
14
|
+
*/
|
|
15
|
+
protected async(promise: Promise<unknown>): void;
|
|
11
16
|
constructor(tx: IDBTransaction, store: IndexedDBStore);
|
|
12
17
|
keys(): Promise<Iterable<number>>;
|
|
13
18
|
get(id: number): Promise<Uint8Array | undefined>;
|
|
19
|
+
getSync(id: number, offset: number, end?: number): Uint8Array | undefined;
|
|
14
20
|
set(id: number, data: Uint8Array): Promise<void>;
|
|
21
|
+
setSync(id: number, data: Uint8Array): void;
|
|
15
22
|
remove(id: number): Promise<void>;
|
|
23
|
+
removeSync(id: number): void;
|
|
16
24
|
commit(): Promise<void>;
|
|
17
25
|
abort(): Promise<void>;
|
|
18
26
|
}
|
|
19
27
|
export declare class IndexedDBStore implements Store {
|
|
20
28
|
protected db: IDBDatabase;
|
|
21
|
-
cache: Map<number,
|
|
29
|
+
cache: Map<number, Uint8Array<ArrayBufferLike>>;
|
|
22
30
|
constructor(db: IDBDatabase);
|
|
23
31
|
sync(): Promise<void>;
|
|
24
32
|
get name(): string;
|
package/dist/IndexedDB.js
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { StoreFS, Transaction } from '@zenfs/core';
|
|
2
|
+
import { log } from 'kerium';
|
|
2
3
|
import { convertException } from './utils.js';
|
|
3
4
|
function wrap(request) {
|
|
4
5
|
return new Promise((resolve, reject) => {
|
|
@@ -12,31 +13,54 @@ function wrap(request) {
|
|
|
12
13
|
/**
|
|
13
14
|
* @internal @hidden
|
|
14
15
|
*/
|
|
15
|
-
export class IndexedDBTransaction extends
|
|
16
|
+
export class IndexedDBTransaction extends Transaction {
|
|
17
|
+
/**
|
|
18
|
+
* Run a asynchronous operation from a sync context. Not magic and subject to (race) conditions.
|
|
19
|
+
* @internal
|
|
20
|
+
*/
|
|
21
|
+
async(promise) {
|
|
22
|
+
this.asyncDone = this.asyncDone.then(() => promise);
|
|
23
|
+
}
|
|
16
24
|
constructor(tx, store) {
|
|
17
25
|
super(store);
|
|
18
26
|
this.tx = tx;
|
|
19
27
|
this.store = store;
|
|
28
|
+
this.asyncDone = Promise.resolve();
|
|
20
29
|
this._idb = tx.objectStore(store.name);
|
|
21
30
|
}
|
|
22
31
|
async keys() {
|
|
23
32
|
return (await wrap(this._idb.getAllKeys())).filter(k => typeof k == 'string').map(k => Number(k));
|
|
24
33
|
}
|
|
25
34
|
async get(id) {
|
|
26
|
-
const data = await wrap(this._idb.get(id
|
|
35
|
+
const data = await wrap(this._idb.get(id));
|
|
27
36
|
if (data)
|
|
28
|
-
this.
|
|
37
|
+
this.store.cache.set(id, new Uint8Array(data));
|
|
29
38
|
return data;
|
|
30
39
|
}
|
|
40
|
+
getSync(id, offset, end) {
|
|
41
|
+
if (!this.store.cache.has(id))
|
|
42
|
+
return;
|
|
43
|
+
const data = new Uint8Array(this.store.cache.get(id));
|
|
44
|
+
end ?? (end = data.byteLength);
|
|
45
|
+
return data.subarray(offset, end);
|
|
46
|
+
}
|
|
31
47
|
async set(id, data) {
|
|
32
|
-
this.
|
|
33
|
-
await wrap(this._idb.put(data, id
|
|
48
|
+
this.store.cache.set(id, new Uint8Array(data));
|
|
49
|
+
await wrap(this._idb.put(data, id));
|
|
50
|
+
}
|
|
51
|
+
setSync(id, data) {
|
|
52
|
+
this.async(this.set(id, data));
|
|
34
53
|
}
|
|
35
54
|
remove(id) {
|
|
36
55
|
this.store.cache.delete(id);
|
|
37
|
-
return wrap(this._idb.delete(id
|
|
56
|
+
return wrap(this._idb.delete(id));
|
|
57
|
+
}
|
|
58
|
+
removeSync(id) {
|
|
59
|
+
this.store.cache.delete(id);
|
|
60
|
+
this.async(this.remove(id));
|
|
38
61
|
}
|
|
39
62
|
async commit() {
|
|
63
|
+
await this.asyncDone;
|
|
40
64
|
const { promise, resolve, reject } = Promise.withResolvers();
|
|
41
65
|
this.tx.oncomplete = () => resolve();
|
|
42
66
|
this.tx.onerror = () => reject(convertException(this.tx.error));
|
|
@@ -44,6 +68,7 @@ export class IndexedDBTransaction extends AsyncTransaction {
|
|
|
44
68
|
return promise;
|
|
45
69
|
}
|
|
46
70
|
async abort() {
|
|
71
|
+
await this.asyncDone;
|
|
47
72
|
const { promise, resolve, reject } = Promise.withResolvers();
|
|
48
73
|
this.tx.onabort = () => resolve();
|
|
49
74
|
this.tx.onerror = () => reject(convertException(this.tx.error));
|
package/dist/access.d.ts
CHANGED
|
@@ -24,7 +24,7 @@ export declare class WebAccessFS extends WebAccessFS_base {
|
|
|
24
24
|
_sync: FileSystem;
|
|
25
25
|
constructor(handle: FileSystemDirectoryHandle);
|
|
26
26
|
remove(path: string): Promise<void>;
|
|
27
|
-
protected removeSync(
|
|
27
|
+
protected removeSync(): void;
|
|
28
28
|
read(path: string, buffer: Uint8Array, offset: number, end: number): Promise<void>;
|
|
29
29
|
write(path: string, buffer: Uint8Array, offset: number): Promise<void>;
|
|
30
30
|
/**
|
|
@@ -33,7 +33,7 @@ export declare class WebAccessFS extends WebAccessFS_base {
|
|
|
33
33
|
*/
|
|
34
34
|
writeFile(path: string, data: Uint8Array): Promise<void>;
|
|
35
35
|
mkdir(path: string, options: CreationOptions): Promise<InodeLike>;
|
|
36
|
-
protected get<const T extends FileSystemHandleKind | null>(kind: T | undefined, path: string
|
|
36
|
+
protected get<const T extends FileSystemHandleKind | null>(kind: T | undefined, path: string): T extends FileSystemHandleKind ? HKindToType<T> : FileSystemHandle;
|
|
37
37
|
}
|
|
38
38
|
declare const _WebAccess: {
|
|
39
39
|
readonly name: "WebAccess";
|
package/dist/access.js
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
|
-
import { Async, constants,
|
|
1
|
+
import { Async, constants, IndexFS, InMemory, Inode } from '@zenfs/core';
|
|
2
2
|
import { basename, dirname, join } from '@zenfs/core/path.js';
|
|
3
3
|
import { S_IFDIR, S_IFMT } from '@zenfs/core/vfs/constants.js';
|
|
4
|
+
import { log, withErrno } from 'kerium';
|
|
4
5
|
import { _throw } from 'utilium';
|
|
5
6
|
import { convertException } from './utils.js';
|
|
6
7
|
function isResizable(buffer) {
|
|
@@ -49,7 +50,7 @@ export class WebAccessFS extends Async(IndexFS) {
|
|
|
49
50
|
continue;
|
|
50
51
|
}
|
|
51
52
|
if (!isKind(handle, 'directory'))
|
|
52
|
-
throw
|
|
53
|
+
throw withErrno('EIO', 'Invalid handle');
|
|
53
54
|
this.index.set(path, new Inode({ mode: 0o777 | constants.S_IFDIR, size: 0 }));
|
|
54
55
|
}
|
|
55
56
|
}
|
|
@@ -60,24 +61,24 @@ export class WebAccessFS extends Async(IndexFS) {
|
|
|
60
61
|
* @hidden
|
|
61
62
|
*/
|
|
62
63
|
this._sync = InMemory.create({ label: 'accessfs-cache' });
|
|
63
|
-
this.attributes.set('no_buffer_resize');
|
|
64
|
+
this.attributes.set('no_buffer_resize', true);
|
|
64
65
|
this._handles.set('/', handle);
|
|
65
66
|
}
|
|
66
67
|
async remove(path) {
|
|
67
68
|
const handle = this.get('directory', dirname(path));
|
|
68
69
|
await handle.removeEntry(basename(path), { recursive: true }).catch(ex => _throw(convertException(ex, path)));
|
|
69
70
|
}
|
|
70
|
-
removeSync(
|
|
71
|
-
throw log.crit(
|
|
71
|
+
removeSync() {
|
|
72
|
+
throw log.crit(withErrno('ENOSYS'));
|
|
72
73
|
}
|
|
73
74
|
async read(path, buffer, offset, end) {
|
|
74
75
|
if (end <= offset)
|
|
75
76
|
return;
|
|
76
|
-
const handle = this.get('file', path
|
|
77
|
+
const handle = this.get('file', path);
|
|
77
78
|
const file = await handle.getFile();
|
|
78
79
|
const data = await file.arrayBuffer();
|
|
79
80
|
if (data.byteLength < end - offset)
|
|
80
|
-
throw
|
|
81
|
+
throw withErrno('ENODATA');
|
|
81
82
|
buffer.set(new Uint8Array(data, offset, end - offset));
|
|
82
83
|
}
|
|
83
84
|
async write(path, buffer, offset) {
|
|
@@ -88,21 +89,21 @@ export class WebAccessFS extends Async(IndexFS) {
|
|
|
88
89
|
}
|
|
89
90
|
const inode = this.index.get(path);
|
|
90
91
|
if (!inode)
|
|
91
|
-
throw
|
|
92
|
+
throw withErrno('ENOENT');
|
|
92
93
|
const isDir = (inode.mode & S_IFMT) == S_IFDIR;
|
|
93
94
|
let handle;
|
|
94
95
|
try {
|
|
95
|
-
handle = this.get(isDir ? 'directory' : 'file', path
|
|
96
|
+
handle = this.get(isDir ? 'directory' : 'file', path);
|
|
96
97
|
}
|
|
97
98
|
catch {
|
|
98
|
-
const parent = this.get('directory', dirname(path)
|
|
99
|
+
const parent = this.get('directory', dirname(path));
|
|
99
100
|
handle = await parent[isDir ? 'getDirectoryHandle' : 'getFileHandle'](basename(path), { create: true }).catch((ex) => _throw(convertException(ex, path)));
|
|
100
101
|
this._handles.set(path, handle);
|
|
101
102
|
}
|
|
102
103
|
if (isDir)
|
|
103
104
|
return;
|
|
104
105
|
if (isKind(handle, 'directory')) {
|
|
105
|
-
log.crit(
|
|
106
|
+
log.crit(withErrno('EIO', 'Mismatch in entry kind on write'));
|
|
106
107
|
return;
|
|
107
108
|
}
|
|
108
109
|
const writable = await handle.createWritable();
|
|
@@ -127,17 +128,17 @@ export class WebAccessFS extends Async(IndexFS) {
|
|
|
127
128
|
}
|
|
128
129
|
async mkdir(path, options) {
|
|
129
130
|
const inode = await super.mkdir(path, options);
|
|
130
|
-
const handle = this.get('directory', dirname(path)
|
|
131
|
+
const handle = this.get('directory', dirname(path));
|
|
131
132
|
const dir = await handle.getDirectoryHandle(basename(path), { create: true }).catch((ex) => _throw(convertException(ex, path)));
|
|
132
133
|
this._handles.set(path, dir);
|
|
133
134
|
return inode;
|
|
134
135
|
}
|
|
135
|
-
get(kind = null, path
|
|
136
|
+
get(kind = null, path) {
|
|
136
137
|
const handle = this._handles.get(path);
|
|
137
138
|
if (!handle)
|
|
138
|
-
throw
|
|
139
|
+
throw withErrno('ENODATA');
|
|
139
140
|
if (kind && !isKind(handle, kind))
|
|
140
|
-
throw
|
|
141
|
+
throw withErrno(kind == 'directory' ? 'ENOTDIR' : 'EISDIR');
|
|
141
142
|
return handle;
|
|
142
143
|
}
|
|
143
144
|
}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { withErrno } from 'kerium';
|
|
2
2
|
let framebufferN = 0;
|
|
3
3
|
/**
|
|
4
4
|
* A frame buffer
|
|
@@ -17,7 +17,7 @@ export const framebuffer = {
|
|
|
17
17
|
}
|
|
18
18
|
const context = canvas.getContext('2d');
|
|
19
19
|
if (!context) {
|
|
20
|
-
throw
|
|
20
|
+
throw withErrno('EIO', 'Could not get context from canvas whilst initializing frame buffer.');
|
|
21
21
|
}
|
|
22
22
|
const image = new ImageData(canvas.width, canvas.height);
|
|
23
23
|
return {
|
package/dist/storage.js
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { withErrno } from 'kerium';
|
|
2
|
+
import { StoreFS, SyncMapTransaction } from '@zenfs/core';
|
|
2
3
|
import { decodeASCII, encodeASCII } from 'utilium';
|
|
3
4
|
/**
|
|
4
5
|
* A synchronous key-value store backed by Storage.
|
|
@@ -36,7 +37,7 @@ export class WebStorageStore {
|
|
|
36
37
|
this.storage.setItem(key.toString(), decodeASCII(data));
|
|
37
38
|
}
|
|
38
39
|
catch {
|
|
39
|
-
throw
|
|
40
|
+
throw withErrno('ENOSPC');
|
|
40
41
|
}
|
|
41
42
|
}
|
|
42
43
|
delete(key) {
|
|
@@ -44,7 +45,7 @@ export class WebStorageStore {
|
|
|
44
45
|
this.storage.removeItem(key.toString());
|
|
45
46
|
}
|
|
46
47
|
catch (e) {
|
|
47
|
-
throw
|
|
48
|
+
throw withErrno('EIO', `Unable to delete '${key}': ${e}`);
|
|
48
49
|
}
|
|
49
50
|
}
|
|
50
51
|
}
|
package/dist/utils.d.ts
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { Exception } from 'kerium';
|
|
2
2
|
/** @internal */
|
|
3
|
-
export type ConvertException =
|
|
3
|
+
export type ConvertException = Exception | DOMException | Error;
|
|
4
4
|
/**
|
|
5
5
|
* Handles converting errors, then rethrowing them
|
|
6
6
|
* @internal
|
|
7
7
|
*/
|
|
8
|
-
export declare function convertException(ex: ConvertException, path?: string
|
|
8
|
+
export declare function convertException(ex: ConvertException, path?: string): Exception;
|
package/dist/utils.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { Exception, Errno } from 'kerium';
|
|
2
2
|
/**
|
|
3
3
|
* Converts a DOMException into an Errno
|
|
4
4
|
* @see https://developer.mozilla.org/Web/API/DOMException
|
|
@@ -57,12 +57,13 @@ function errnoForDOMException(ex) {
|
|
|
57
57
|
* Handles converting errors, then rethrowing them
|
|
58
58
|
* @internal
|
|
59
59
|
*/
|
|
60
|
-
export function convertException(ex, path
|
|
61
|
-
if (ex instanceof
|
|
60
|
+
export function convertException(ex, path) {
|
|
61
|
+
if (ex instanceof Exception)
|
|
62
62
|
return ex;
|
|
63
63
|
const code = ex instanceof DOMException ? Errno[errnoForDOMException(ex)] : Errno.EIO;
|
|
64
|
-
const error = new
|
|
64
|
+
const error = new Exception(code, ex.message);
|
|
65
65
|
error.stack = ex.stack;
|
|
66
|
+
Error.captureStackTrace?.(error, convertException);
|
|
66
67
|
error.cause = ex.cause;
|
|
67
68
|
return error;
|
|
68
69
|
}
|
package/dist/xml.js
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { withErrno } from 'kerium';
|
|
2
|
+
import { _inode_fields, constants, FileSystem, Inode, Sync } from '@zenfs/core';
|
|
2
3
|
import { basename, dirname } from '@zenfs/core/path.js';
|
|
3
4
|
import { decodeASCII, encodeASCII } from 'utilium';
|
|
4
5
|
function get_stats(node) {
|
|
@@ -66,15 +67,15 @@ export class XMLFS extends Sync(FileSystem) {
|
|
|
66
67
|
unlinkSync(path) {
|
|
67
68
|
const node = this.get('unlink', path);
|
|
68
69
|
if (get_stats(node).mode & constants.S_IFDIR)
|
|
69
|
-
throw
|
|
70
|
+
throw withErrno('EISDIR');
|
|
70
71
|
this.remove('unlink', node, path);
|
|
71
72
|
}
|
|
72
73
|
rmdirSync(path) {
|
|
73
74
|
const node = this.get('rmdir', path);
|
|
74
75
|
if (node.textContent?.length)
|
|
75
|
-
throw
|
|
76
|
+
throw withErrno('ENOTEMPTY');
|
|
76
77
|
if (!(get_stats(node).mode & constants.S_IFDIR))
|
|
77
|
-
throw
|
|
78
|
+
throw withErrno('ENOTDIR');
|
|
78
79
|
this.remove('rmdir', node, path);
|
|
79
80
|
}
|
|
80
81
|
mkdirSync(path, options) {
|
|
@@ -90,12 +91,12 @@ export class XMLFS extends Sync(FileSystem) {
|
|
|
90
91
|
readdirSync(path) {
|
|
91
92
|
const node = this.get('readdir', path);
|
|
92
93
|
if (!(get_stats(node).mode & constants.S_IFDIR))
|
|
93
|
-
throw
|
|
94
|
+
throw withErrno('ENOTDIR');
|
|
94
95
|
try {
|
|
95
96
|
return JSON.parse(node.textContent);
|
|
96
97
|
}
|
|
97
98
|
catch (e) {
|
|
98
|
-
throw
|
|
99
|
+
throw withErrno('EIO', 'Invalid directory listing: ' + e);
|
|
99
100
|
}
|
|
100
101
|
}
|
|
101
102
|
linkSync(target, link) {
|
|
@@ -124,16 +125,16 @@ export class XMLFS extends Sync(FileSystem) {
|
|
|
124
125
|
get(syscall, path) {
|
|
125
126
|
const nodes = this.root.children;
|
|
126
127
|
if (!nodes)
|
|
127
|
-
throw
|
|
128
|
+
throw withErrno('EIO');
|
|
128
129
|
for (let i = 0; i < nodes.length; i++) {
|
|
129
130
|
if (get_paths(nodes[i]).includes(path))
|
|
130
131
|
return nodes[i];
|
|
131
132
|
}
|
|
132
|
-
throw
|
|
133
|
+
throw withErrno('ENOENT');
|
|
133
134
|
}
|
|
134
135
|
create(syscall, path, stats) {
|
|
135
136
|
if (this.existsSync(path))
|
|
136
|
-
throw
|
|
137
|
+
throw withErrno('EEXIST');
|
|
137
138
|
const node = document.createElement('file');
|
|
138
139
|
this.add(syscall, node, path);
|
|
139
140
|
set_stats(node, new Inode({
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@zenfs/dom",
|
|
3
|
-
"version": "1.1.
|
|
3
|
+
"version": "1.1.7",
|
|
4
4
|
"description": "DOM backends for ZenFS",
|
|
5
5
|
"funding": {
|
|
6
6
|
"type": "individual",
|
|
@@ -61,8 +61,9 @@
|
|
|
61
61
|
"typescript-eslint": "^8.8.1"
|
|
62
62
|
},
|
|
63
63
|
"peerDependencies": {
|
|
64
|
-
"@zenfs/core": "^2.
|
|
65
|
-
"
|
|
64
|
+
"@zenfs/core": "^2.1.0",
|
|
65
|
+
"kerium": "^1.3.4",
|
|
66
|
+
"utilium": "^2.0.0"
|
|
66
67
|
},
|
|
67
68
|
"keywords": [
|
|
68
69
|
"filesystem",
|