@zenfs/core 2.0.0 → 2.1.1
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/backends/backend.js +6 -5
- package/dist/backends/cow.d.ts +2 -2
- package/dist/backends/cow.js +39 -58
- package/dist/backends/fetch.js +27 -29
- package/dist/backends/passthrough.d.ts +2 -3
- package/dist/backends/passthrough.js +84 -199
- package/dist/backends/port.d.ts +16 -3
- package/dist/backends/port.js +61 -30
- package/dist/backends/single_buffer.d.ts +52 -46
- package/dist/backends/single_buffer.js +462 -219
- package/dist/backends/store/fs.d.ts +16 -10
- package/dist/backends/store/fs.js +227 -242
- package/dist/backends/store/store.d.ts +3 -3
- package/dist/backends/store/store.js +11 -10
- package/dist/config.d.ts +2 -2
- package/dist/config.js +10 -11
- package/dist/internal/devices.d.ts +2 -2
- package/dist/internal/devices.js +39 -49
- package/dist/internal/error.d.ts +9 -204
- package/dist/internal/error.js +19 -288
- package/dist/internal/file_index.d.ts +1 -1
- package/dist/internal/file_index.js +9 -9
- package/dist/internal/filesystem.d.ts +23 -8
- package/dist/internal/index.d.ts +1 -1
- package/dist/internal/index.js +1 -1
- package/dist/internal/index_fs.d.ts +2 -2
- package/dist/internal/index_fs.js +19 -19
- package/dist/internal/inode.d.ts +81 -103
- package/dist/internal/inode.js +336 -195
- package/dist/mixins/async.js +32 -28
- package/dist/mixins/mutexed.d.ts +4 -4
- package/dist/mixins/mutexed.js +39 -39
- package/dist/mixins/readonly.d.ts +2 -2
- package/dist/mixins/readonly.js +20 -20
- package/dist/mixins/sync.js +2 -2
- package/dist/polyfills.js +1 -1
- package/dist/readline.js +1 -1
- package/dist/utils.d.ts +8 -5
- package/dist/utils.js +14 -17
- package/dist/vfs/acl.d.ts +8 -8
- package/dist/vfs/acl.js +66 -47
- package/dist/vfs/async.d.ts +2 -2
- package/dist/vfs/async.js +6 -8
- package/dist/vfs/dir.d.ts +1 -1
- package/dist/vfs/dir.js +3 -4
- package/dist/vfs/file.js +33 -24
- package/dist/vfs/flags.js +3 -3
- package/dist/vfs/ioctl.d.ts +8 -7
- package/dist/vfs/ioctl.js +132 -27
- package/dist/vfs/promises.d.ts +3 -3
- package/dist/vfs/promises.js +200 -235
- package/dist/vfs/shared.d.ts +1 -12
- package/dist/vfs/shared.js +7 -35
- package/dist/vfs/streams.js +9 -9
- package/dist/vfs/sync.d.ts +1 -2
- package/dist/vfs/sync.js +158 -170
- package/dist/vfs/watchers.js +8 -8
- package/dist/vfs/xattr.js +89 -106
- package/package.json +5 -3
- package/scripts/test.js +2 -2
- package/tests/assignment.ts +1 -1
- package/tests/backend/port.test.ts +4 -4
- package/tests/backend/single-buffer.test.ts +39 -10
- package/tests/backend/single-buffer.worker.js +30 -0
- package/tests/common/context.test.ts +2 -2
- package/tests/common/mutex.test.ts +9 -9
- package/tests/fetch/fetch.ts +1 -1
- package/tests/fetch/run.sh +1 -1
- package/tests/fs/append.test.ts +4 -4
- package/tests/fs/directory.test.ts +25 -25
- package/tests/fs/errors.test.ts +15 -19
- package/tests/fs/links.test.ts +3 -2
- package/tests/fs/open.test.ts +4 -21
- package/tests/fs/permissions.test.ts +8 -13
- package/tests/fs/read.test.ts +10 -9
- package/tests/fs/readFile.test.ts +8 -24
- package/tests/fs/rename.test.ts +4 -9
- package/tests/fs/stat.test.ts +2 -2
- package/tests/fs/times.test.ts +6 -6
- package/tests/fs/truncate.test.ts +8 -36
- package/tests/fs/watch.test.ts +10 -10
- package/tests/fs/write.test.ts +77 -13
- package/tests/fs/xattr.test.ts +7 -7
- package/tests/logs.js +2 -2
- package/tests/setup/port.ts +6 -0
- package/dist/internal/log.d.ts +0 -139
- package/dist/internal/log.js +0 -219
- package/tests/fs/writeFile.test.ts +0 -70
|
@@ -50,11 +50,10 @@ var __disposeResources = (this && this.__disposeResources) || (function (Suppres
|
|
|
50
50
|
var e = new Error(message);
|
|
51
51
|
return e.name = "SuppressedError", e.error = error, e.suppressed = suppressed, e;
|
|
52
52
|
});
|
|
53
|
-
import {
|
|
53
|
+
import { warn } from 'kerium/log';
|
|
54
54
|
import { FileSystem } from '../internal/filesystem.js';
|
|
55
55
|
import { isDirectory } from '../internal/inode.js';
|
|
56
56
|
import { resolve } from '../path.js';
|
|
57
|
-
import { warn } from '../internal/log.js';
|
|
58
57
|
export class PassthroughFS extends FileSystem {
|
|
59
58
|
constructor(nodeFS, prefix) {
|
|
60
59
|
super(0x6e6f6465, 'nodefs');
|
|
@@ -71,327 +70,213 @@ export class PassthroughFS extends FileSystem {
|
|
|
71
70
|
path(path) {
|
|
72
71
|
return this.prefix + path;
|
|
73
72
|
}
|
|
74
|
-
error(err, path) {
|
|
75
|
-
const error = err;
|
|
76
|
-
throw ErrnoError.With(error.code, path, error.syscall);
|
|
77
|
-
}
|
|
78
73
|
/**
|
|
79
74
|
* Rename a file or directory.
|
|
80
75
|
*/
|
|
81
76
|
async rename(oldPath, newPath) {
|
|
82
|
-
|
|
83
|
-
await this.nodeFS.promises.rename(this.path(oldPath), this.path(newPath));
|
|
84
|
-
}
|
|
85
|
-
catch (err) {
|
|
86
|
-
this.error(err, oldPath);
|
|
87
|
-
}
|
|
77
|
+
await this.nodeFS.promises.rename(this.path(oldPath), this.path(newPath));
|
|
88
78
|
}
|
|
89
79
|
/**
|
|
90
80
|
* Rename a file or directory synchronously.
|
|
91
81
|
*/
|
|
92
82
|
renameSync(oldPath, newPath) {
|
|
93
|
-
|
|
94
|
-
this.nodeFS.renameSync(this.path(oldPath), this.path(newPath));
|
|
95
|
-
}
|
|
96
|
-
catch (err) {
|
|
97
|
-
this.error(err, oldPath);
|
|
98
|
-
}
|
|
83
|
+
this.nodeFS.renameSync(this.path(oldPath), this.path(newPath));
|
|
99
84
|
}
|
|
100
85
|
/**
|
|
101
86
|
* Get file statistics.
|
|
102
87
|
*/
|
|
103
88
|
async stat(path) {
|
|
104
|
-
|
|
105
|
-
return await this.nodeFS.promises.stat(this.path(path));
|
|
106
|
-
}
|
|
107
|
-
catch (err) {
|
|
108
|
-
this.error(err, path);
|
|
109
|
-
}
|
|
89
|
+
return await this.nodeFS.promises.stat(this.path(path));
|
|
110
90
|
}
|
|
111
91
|
/**
|
|
112
92
|
* Get file statistics synchronously.
|
|
113
93
|
*/
|
|
114
94
|
statSync(path) {
|
|
115
|
-
|
|
116
|
-
return this.nodeFS.statSync(this.path(path));
|
|
117
|
-
}
|
|
118
|
-
catch (err) {
|
|
119
|
-
this.error(err, path);
|
|
120
|
-
}
|
|
95
|
+
return this.nodeFS.statSync(this.path(path));
|
|
121
96
|
}
|
|
122
97
|
async touch(path, metadata) {
|
|
98
|
+
const env_1 = { stack: [], error: void 0, hasError: false };
|
|
123
99
|
try {
|
|
124
|
-
const
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
await handle.chown(metadata.uid, metadata.gid);
|
|
129
|
-
await handle.utimes(metadata.atimeMs, metadata.mtimeMs);
|
|
130
|
-
}
|
|
131
|
-
catch (e_1) {
|
|
132
|
-
env_1.error = e_1;
|
|
133
|
-
env_1.hasError = true;
|
|
134
|
-
}
|
|
135
|
-
finally {
|
|
136
|
-
const result_1 = __disposeResources(env_1);
|
|
137
|
-
if (result_1)
|
|
138
|
-
await result_1;
|
|
139
|
-
}
|
|
100
|
+
const handle = __addDisposableResource(env_1, await this.nodeFS.promises.open(this.path(path), 'w'), true);
|
|
101
|
+
await handle.chmod(metadata.mode);
|
|
102
|
+
await handle.chown(metadata.uid, metadata.gid);
|
|
103
|
+
await handle.utimes(metadata.atimeMs, metadata.mtimeMs);
|
|
140
104
|
}
|
|
141
|
-
catch (
|
|
142
|
-
|
|
105
|
+
catch (e_1) {
|
|
106
|
+
env_1.error = e_1;
|
|
107
|
+
env_1.hasError = true;
|
|
108
|
+
}
|
|
109
|
+
finally {
|
|
110
|
+
const result_1 = __disposeResources(env_1);
|
|
111
|
+
if (result_1)
|
|
112
|
+
await result_1;
|
|
143
113
|
}
|
|
144
114
|
}
|
|
145
115
|
touchSync(path, metadata) {
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
this.nodeFS.utimesSync(this.path(path), metadata.atimeMs, metadata.mtimeMs);
|
|
150
|
-
}
|
|
151
|
-
catch (err) {
|
|
152
|
-
this.error(err, path);
|
|
153
|
-
}
|
|
116
|
+
this.nodeFS.chmodSync(this.path(path), metadata.mode);
|
|
117
|
+
this.nodeFS.chownSync(this.path(path), metadata.uid, metadata.gid);
|
|
118
|
+
this.nodeFS.utimesSync(this.path(path), metadata.atimeMs, metadata.mtimeMs);
|
|
154
119
|
}
|
|
155
120
|
/**
|
|
156
121
|
* Unlink (delete) a file.
|
|
157
122
|
*/
|
|
158
123
|
async unlink(path) {
|
|
159
|
-
|
|
160
|
-
await this.nodeFS.promises.unlink(this.path(path));
|
|
161
|
-
}
|
|
162
|
-
catch (err) {
|
|
163
|
-
this.error(err, path);
|
|
164
|
-
}
|
|
124
|
+
await this.nodeFS.promises.unlink(this.path(path));
|
|
165
125
|
}
|
|
166
126
|
/**
|
|
167
127
|
* Unlink (delete) a file synchronously.
|
|
168
128
|
*/
|
|
169
129
|
unlinkSync(path) {
|
|
170
|
-
|
|
171
|
-
this.nodeFS.unlinkSync(this.path(path));
|
|
172
|
-
}
|
|
173
|
-
catch (err) {
|
|
174
|
-
this.error(err, path);
|
|
175
|
-
}
|
|
130
|
+
this.nodeFS.unlinkSync(this.path(path));
|
|
176
131
|
}
|
|
177
132
|
/**
|
|
178
133
|
* Create a directory.
|
|
179
134
|
*/
|
|
180
135
|
async mkdir(path, options) {
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
return await this.nodeFS.promises.stat(this.path(path));
|
|
184
|
-
}
|
|
185
|
-
catch (err) {
|
|
186
|
-
this.error(err, path);
|
|
187
|
-
}
|
|
136
|
+
await this.nodeFS.promises.mkdir(this.path(path), options);
|
|
137
|
+
return await this.nodeFS.promises.stat(this.path(path));
|
|
188
138
|
}
|
|
189
139
|
/**
|
|
190
140
|
* Create a directory synchronously.
|
|
191
141
|
*/
|
|
192
142
|
mkdirSync(path, options) {
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
return this.nodeFS.statSync(this.path(path));
|
|
196
|
-
}
|
|
197
|
-
catch (err) {
|
|
198
|
-
this.error(err, path);
|
|
199
|
-
}
|
|
143
|
+
this.nodeFS.mkdirSync(this.path(path), options);
|
|
144
|
+
return this.nodeFS.statSync(this.path(path));
|
|
200
145
|
}
|
|
201
146
|
/**
|
|
202
147
|
* Read the contents of a directory.
|
|
203
148
|
*/
|
|
204
149
|
async readdir(path) {
|
|
205
|
-
|
|
206
|
-
return await this.nodeFS.promises.readdir(this.path(path));
|
|
207
|
-
}
|
|
208
|
-
catch (err) {
|
|
209
|
-
this.error(err, path);
|
|
210
|
-
}
|
|
150
|
+
return await this.nodeFS.promises.readdir(this.path(path));
|
|
211
151
|
}
|
|
212
152
|
/**
|
|
213
153
|
* Read the contents of a directory synchronously.
|
|
214
154
|
*/
|
|
215
155
|
readdirSync(path) {
|
|
216
|
-
|
|
217
|
-
return this.nodeFS.readdirSync(this.path(path));
|
|
218
|
-
}
|
|
219
|
-
catch (err) {
|
|
220
|
-
this.error(err, path);
|
|
221
|
-
}
|
|
156
|
+
return this.nodeFS.readdirSync(this.path(path));
|
|
222
157
|
}
|
|
223
158
|
/**
|
|
224
159
|
* Create a file.
|
|
225
160
|
*/
|
|
226
161
|
async createFile(path, options) {
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
162
|
+
if (isDirectory(options)) {
|
|
163
|
+
await this.nodeFS.promises.mkdir(this.path(path), { mode: options.mode });
|
|
164
|
+
}
|
|
165
|
+
else {
|
|
166
|
+
const env_2 = { stack: [], error: void 0, hasError: false };
|
|
167
|
+
try {
|
|
168
|
+
const handle = __addDisposableResource(env_2, await this.nodeFS.promises.open(this.path(path), 'wx'), true);
|
|
169
|
+
await handle.close();
|
|
230
170
|
}
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
env_2.hasError = true;
|
|
240
|
-
}
|
|
241
|
-
finally {
|
|
242
|
-
const result_2 = __disposeResources(env_2);
|
|
243
|
-
if (result_2)
|
|
244
|
-
await result_2;
|
|
245
|
-
}
|
|
171
|
+
catch (e_2) {
|
|
172
|
+
env_2.error = e_2;
|
|
173
|
+
env_2.hasError = true;
|
|
174
|
+
}
|
|
175
|
+
finally {
|
|
176
|
+
const result_2 = __disposeResources(env_2);
|
|
177
|
+
if (result_2)
|
|
178
|
+
await result_2;
|
|
246
179
|
}
|
|
247
|
-
return await this.nodeFS.promises.stat(this.path(path));
|
|
248
|
-
}
|
|
249
|
-
catch (err) {
|
|
250
|
-
this.error(err, path);
|
|
251
180
|
}
|
|
181
|
+
return await this.nodeFS.promises.stat(this.path(path));
|
|
252
182
|
}
|
|
253
183
|
/**
|
|
254
184
|
* Create a file synchronously.
|
|
255
185
|
*/
|
|
256
186
|
createFileSync(path, options) {
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
this.nodeFS.mkdirSync(this.path(path), { mode: options.mode });
|
|
260
|
-
}
|
|
261
|
-
else {
|
|
262
|
-
const fd = this.nodeFS.openSync(this.path(path), 'wx');
|
|
263
|
-
this.nodeFS.closeSync(fd);
|
|
264
|
-
}
|
|
265
|
-
return this.nodeFS.statSync(this.path(path));
|
|
187
|
+
if (isDirectory(options)) {
|
|
188
|
+
this.nodeFS.mkdirSync(this.path(path), { mode: options.mode });
|
|
266
189
|
}
|
|
267
|
-
|
|
268
|
-
this.
|
|
190
|
+
else {
|
|
191
|
+
const fd = this.nodeFS.openSync(this.path(path), 'wx');
|
|
192
|
+
this.nodeFS.closeSync(fd);
|
|
269
193
|
}
|
|
194
|
+
return this.nodeFS.statSync(this.path(path));
|
|
270
195
|
}
|
|
271
196
|
/**
|
|
272
197
|
* Remove a directory.
|
|
273
198
|
*/
|
|
274
199
|
async rmdir(path) {
|
|
275
|
-
|
|
276
|
-
await this.nodeFS.promises.rmdir(this.path(path));
|
|
277
|
-
}
|
|
278
|
-
catch (err) {
|
|
279
|
-
this.error(err, path);
|
|
280
|
-
}
|
|
200
|
+
await this.nodeFS.promises.rmdir(this.path(path));
|
|
281
201
|
}
|
|
282
202
|
/**
|
|
283
203
|
* Remove a directory synchronously.
|
|
284
204
|
*/
|
|
285
205
|
rmdirSync(path) {
|
|
286
|
-
|
|
287
|
-
this.nodeFS.rmdirSync(this.path(path));
|
|
288
|
-
}
|
|
289
|
-
catch (err) {
|
|
290
|
-
this.error(err, path);
|
|
291
|
-
}
|
|
206
|
+
this.nodeFS.rmdirSync(this.path(path));
|
|
292
207
|
}
|
|
293
208
|
/**
|
|
294
209
|
* Synchronize data to the file system.
|
|
295
210
|
*/
|
|
296
|
-
async sync(
|
|
211
|
+
async sync() {
|
|
297
212
|
warn('Sync on passthrough is unnecessary');
|
|
298
213
|
}
|
|
299
214
|
/**
|
|
300
215
|
* Synchronize data to the file system synchronously.
|
|
301
216
|
*/
|
|
302
|
-
syncSync(
|
|
217
|
+
syncSync() {
|
|
303
218
|
warn('Sync on passthrough is unnecessary');
|
|
304
219
|
}
|
|
305
220
|
/**
|
|
306
221
|
* Create a hard link.
|
|
307
222
|
*/
|
|
308
223
|
async link(target, link) {
|
|
309
|
-
|
|
310
|
-
await this.nodeFS.promises.link(this.path(target), this.path(link));
|
|
311
|
-
}
|
|
312
|
-
catch (err) {
|
|
313
|
-
this.error(err, target);
|
|
314
|
-
}
|
|
224
|
+
await this.nodeFS.promises.link(this.path(target), this.path(link));
|
|
315
225
|
}
|
|
316
226
|
/**
|
|
317
227
|
* Create a hard link synchronously.
|
|
318
228
|
*/
|
|
319
229
|
linkSync(target, link) {
|
|
320
|
-
|
|
321
|
-
this.nodeFS.linkSync(this.path(target), this.path(link));
|
|
322
|
-
}
|
|
323
|
-
catch (err) {
|
|
324
|
-
this.error(err, target);
|
|
325
|
-
}
|
|
230
|
+
this.nodeFS.linkSync(this.path(target), this.path(link));
|
|
326
231
|
}
|
|
327
232
|
async read(path, buffer, offset, end) {
|
|
233
|
+
const env_3 = { stack: [], error: void 0, hasError: false };
|
|
328
234
|
try {
|
|
329
|
-
const
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
env_3.error = e_3;
|
|
336
|
-
env_3.hasError = true;
|
|
337
|
-
}
|
|
338
|
-
finally {
|
|
339
|
-
const result_3 = __disposeResources(env_3);
|
|
340
|
-
if (result_3)
|
|
341
|
-
await result_3;
|
|
342
|
-
}
|
|
235
|
+
const handle = __addDisposableResource(env_3, await this.nodeFS.promises.open(this.path(path), 'r'), true);
|
|
236
|
+
await handle.read({ buffer, offset, length: end - offset });
|
|
237
|
+
}
|
|
238
|
+
catch (e_3) {
|
|
239
|
+
env_3.error = e_3;
|
|
240
|
+
env_3.hasError = true;
|
|
343
241
|
}
|
|
344
|
-
|
|
345
|
-
|
|
242
|
+
finally {
|
|
243
|
+
const result_3 = __disposeResources(env_3);
|
|
244
|
+
if (result_3)
|
|
245
|
+
await result_3;
|
|
346
246
|
}
|
|
347
247
|
}
|
|
348
248
|
readSync(path, buffer, offset, end) {
|
|
349
|
-
|
|
249
|
+
const fd = this.nodeFS.openSync(this.path(path), 'r');
|
|
350
250
|
try {
|
|
351
|
-
fd = this.nodeFS.openSync(this.path(path), 'r');
|
|
352
251
|
this.nodeFS.readSync(fd, buffer, { offset, length: end - offset });
|
|
353
252
|
}
|
|
354
|
-
catch (err) {
|
|
355
|
-
this.error(err, path);
|
|
356
|
-
}
|
|
357
253
|
finally {
|
|
358
|
-
|
|
359
|
-
this.nodeFS.closeSync(fd);
|
|
254
|
+
this.nodeFS.closeSync(fd);
|
|
360
255
|
}
|
|
361
256
|
}
|
|
362
257
|
async write(path, buffer, offset) {
|
|
258
|
+
const env_4 = { stack: [], error: void 0, hasError: false };
|
|
363
259
|
try {
|
|
364
|
-
const
|
|
365
|
-
|
|
366
|
-
const handle = __addDisposableResource(env_4, await this.nodeFS.promises.open(this.path(path), 'w'), true);
|
|
367
|
-
await handle.write(buffer, offset);
|
|
368
|
-
}
|
|
369
|
-
catch (e_4) {
|
|
370
|
-
env_4.error = e_4;
|
|
371
|
-
env_4.hasError = true;
|
|
372
|
-
}
|
|
373
|
-
finally {
|
|
374
|
-
const result_4 = __disposeResources(env_4);
|
|
375
|
-
if (result_4)
|
|
376
|
-
await result_4;
|
|
377
|
-
}
|
|
260
|
+
const handle = __addDisposableResource(env_4, await this.nodeFS.promises.open(this.path(path), 'w'), true);
|
|
261
|
+
await handle.write(buffer, offset);
|
|
378
262
|
}
|
|
379
|
-
catch (
|
|
380
|
-
|
|
263
|
+
catch (e_4) {
|
|
264
|
+
env_4.error = e_4;
|
|
265
|
+
env_4.hasError = true;
|
|
266
|
+
}
|
|
267
|
+
finally {
|
|
268
|
+
const result_4 = __disposeResources(env_4);
|
|
269
|
+
if (result_4)
|
|
270
|
+
await result_4;
|
|
381
271
|
}
|
|
382
272
|
}
|
|
383
273
|
writeSync(path, buffer, offset) {
|
|
384
|
-
|
|
274
|
+
const fd = this.nodeFS.openSync(this.path(path), 'w');
|
|
385
275
|
try {
|
|
386
|
-
fd = this.nodeFS.openSync(this.path(path), 'w');
|
|
387
276
|
this.nodeFS.writeSync(fd, buffer, offset);
|
|
388
277
|
}
|
|
389
|
-
catch (err) {
|
|
390
|
-
this.error(err, path);
|
|
391
|
-
}
|
|
392
278
|
finally {
|
|
393
|
-
|
|
394
|
-
this.nodeFS.closeSync(fd);
|
|
279
|
+
this.nodeFS.closeSync(fd);
|
|
395
280
|
}
|
|
396
281
|
}
|
|
397
282
|
}
|
package/dist/backends/port.d.ts
CHANGED
|
@@ -48,7 +48,7 @@ export interface RPCMethods {
|
|
|
48
48
|
touch(path: string, metadata: Uint8Array): void;
|
|
49
49
|
exists(path: string): boolean;
|
|
50
50
|
link(target: string, link: string): void;
|
|
51
|
-
sync(
|
|
51
|
+
sync(): void;
|
|
52
52
|
read(path: string, buffer: Uint8Array, start: number, end: number): Uint8Array;
|
|
53
53
|
write(path: string, buffer: Uint8Array, offset: number): void;
|
|
54
54
|
stat(path: string): Uint8Array;
|
|
@@ -74,6 +74,14 @@ interface RPCRequest<TMethod extends RPCMethod = RPCMethod> extends RPCMessage {
|
|
|
74
74
|
method: TMethod;
|
|
75
75
|
args: Parameters<RPCMethods[TMethod]>;
|
|
76
76
|
}
|
|
77
|
+
/**
|
|
78
|
+
* An RPC executor
|
|
79
|
+
* @internal @hidden
|
|
80
|
+
*/
|
|
81
|
+
interface RPCExecutor extends PromiseWithResolvers<any> {
|
|
82
|
+
fs: PortFS;
|
|
83
|
+
timeout: ReturnType<typeof setTimeout>;
|
|
84
|
+
}
|
|
77
85
|
export declare function attach<T extends RPCMessage>(port: RPCPort, handler: (message: T) => unknown): void;
|
|
78
86
|
export declare function detach<T extends RPCMessage>(port: RPCPort, handler: (message: T) => unknown): void;
|
|
79
87
|
export declare function catchMessages<T extends Backend>(port: RPCPort): (fs: FilesystemOf<T>) => Promise<void>;
|
|
@@ -93,7 +101,12 @@ declare const PortFS_base: import("../index.js").Mixin<typeof FileSystem, import
|
|
|
93
101
|
export declare class PortFS extends PortFS_base {
|
|
94
102
|
readonly options: PortOptions;
|
|
95
103
|
readonly port: RPCPort;
|
|
96
|
-
|
|
104
|
+
/**
|
|
105
|
+
* A map of outstanding RPC requests
|
|
106
|
+
* @internal @hidden
|
|
107
|
+
*/
|
|
108
|
+
readonly _executors: Map<string, RPCExecutor>;
|
|
109
|
+
/**
|
|
97
110
|
* @hidden
|
|
98
111
|
*/
|
|
99
112
|
_sync: import("./index.js").StoreFS<import("./memory.js").InMemoryStore>;
|
|
@@ -106,7 +119,7 @@ export declare class PortFS extends PortFS_base {
|
|
|
106
119
|
rename(oldPath: string, newPath: string): Promise<void>;
|
|
107
120
|
stat(path: string): Promise<Inode>;
|
|
108
121
|
touch(path: string, metadata: InodeLike | Inode): Promise<void>;
|
|
109
|
-
sync(
|
|
122
|
+
sync(): Promise<void>;
|
|
110
123
|
createFile(path: string, options: CreationOptions): Promise<Inode>;
|
|
111
124
|
unlink(path: string): Promise<void>;
|
|
112
125
|
rmdir(path: string): Promise<void>;
|
package/dist/backends/port.js
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { Errno, Exception, withErrno } from 'kerium';
|
|
2
|
+
import { err, info } from 'kerium/log';
|
|
3
|
+
import { pick } from 'utilium';
|
|
2
4
|
import { resolveMountConfig } from '../config.js';
|
|
3
|
-
import { Errno, ErrnoError } from '../internal/error.js';
|
|
4
5
|
import { FileSystem } from '../internal/filesystem.js';
|
|
5
6
|
import { Inode } from '../internal/inode.js';
|
|
6
|
-
import { err, info } from '../internal/log.js';
|
|
7
7
|
import { Async } from '../mixins/async.js';
|
|
8
8
|
import '../polyfills.js';
|
|
9
9
|
import { _fnOpt } from './backend.js';
|
|
@@ -11,24 +11,38 @@ import { InMemory } from './memory.js';
|
|
|
11
11
|
function isRPCMessage(arg) {
|
|
12
12
|
return typeof arg == 'object' && arg != null && '_zenfs' in arg && !!arg._zenfs;
|
|
13
13
|
}
|
|
14
|
+
function disposeExecutors(id) {
|
|
15
|
+
const executor = executors.get(id);
|
|
16
|
+
if (!executor)
|
|
17
|
+
return;
|
|
18
|
+
if (executor.timeout) {
|
|
19
|
+
clearTimeout(executor.timeout);
|
|
20
|
+
if (typeof executor.timeout == 'object')
|
|
21
|
+
executor.timeout.unref();
|
|
22
|
+
}
|
|
23
|
+
executor.fs._executors.delete(id);
|
|
24
|
+
executors.delete(id);
|
|
25
|
+
}
|
|
26
|
+
/**
|
|
27
|
+
* A map of *all* outstanding RPC requests
|
|
28
|
+
*/
|
|
14
29
|
const executors = new Map();
|
|
15
|
-
function request(request, { port, timeout = 1000, fs }
|
|
30
|
+
function request(request, { port, timeout: ms = 1000, fs }) {
|
|
16
31
|
const stack = '\n' + new Error().stack.slice('Error:'.length);
|
|
17
32
|
if (!port)
|
|
18
|
-
throw err(
|
|
33
|
+
throw err(withErrno('EINVAL', 'Can not make an RPC request without a port'));
|
|
19
34
|
const { resolve, reject, promise } = Promise.withResolvers();
|
|
20
35
|
const id = Math.random().toString(16).slice(10);
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
const _ = setTimeout(() => {
|
|
24
|
-
const error = err(new ErrnoError(Errno.EIO, 'RPC Failed', typeof request.args[0] == 'string' ? request.args[0] : '', request.method), {
|
|
25
|
-
fs,
|
|
26
|
-
});
|
|
36
|
+
const timeout = setTimeout(() => {
|
|
37
|
+
const error = err(withErrno('EIO', 'RPC Failed'));
|
|
27
38
|
error.stack += stack;
|
|
39
|
+
disposeExecutors(id);
|
|
28
40
|
reject(error);
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
41
|
+
}, ms);
|
|
42
|
+
const executor = { resolve, reject, promise, fs, timeout };
|
|
43
|
+
fs._executors.set(id, executor);
|
|
44
|
+
executors.set(id, executor);
|
|
45
|
+
port.postMessage({ ...request, _zenfs: true, id, stack });
|
|
32
46
|
return promise;
|
|
33
47
|
}
|
|
34
48
|
// Why Typescript, WHY does the type need to be asserted even when the method is explicitly checked?
|
|
@@ -40,25 +54,25 @@ function handleResponse(response) {
|
|
|
40
54
|
if (!isRPCMessage(response))
|
|
41
55
|
return;
|
|
42
56
|
if (!executors.has(response.id)) {
|
|
43
|
-
const error = err(
|
|
57
|
+
const error = err(withErrno('EIO', 'Invalid RPC id: ' + response.id));
|
|
44
58
|
error.stack += response.stack;
|
|
45
59
|
throw error;
|
|
46
60
|
}
|
|
47
61
|
const { resolve, reject } = executors.get(response.id);
|
|
48
62
|
if (response.error) {
|
|
49
|
-
const e =
|
|
63
|
+
const e = Exception.fromJSON({ code: 'EIO', errno: Errno.EIO, ...response.error });
|
|
50
64
|
e.stack += response.stack;
|
|
65
|
+
disposeExecutors(response.id);
|
|
51
66
|
reject(e);
|
|
52
|
-
executors.delete(response.id);
|
|
53
67
|
return;
|
|
54
68
|
}
|
|
69
|
+
disposeExecutors(response.id);
|
|
55
70
|
resolve(__responseMethod(response, 'stat', 'createFile', 'mkdir') ? new Inode(response.value) : response.value);
|
|
56
|
-
executors.delete(response.id);
|
|
57
71
|
return;
|
|
58
72
|
}
|
|
59
73
|
export function attach(port, handler) {
|
|
60
74
|
if (!port)
|
|
61
|
-
throw err(
|
|
75
|
+
throw err(withErrno('EINVAL', 'Cannot attach to non-existent port'));
|
|
62
76
|
info('Attached handler to port: ' + handler.name);
|
|
63
77
|
port['on' in port ? 'on' : 'addEventListener']('message', (message) => {
|
|
64
78
|
handler(typeof message == 'object' && message !== null && 'data' in message ? message.data : message);
|
|
@@ -66,7 +80,7 @@ export function attach(port, handler) {
|
|
|
66
80
|
}
|
|
67
81
|
export function detach(port, handler) {
|
|
68
82
|
if (!port)
|
|
69
|
-
throw err(
|
|
83
|
+
throw err(withErrno('EINVAL', 'Cannot detach from non-existent port'));
|
|
70
84
|
info('Detached handler from port: ' + handler.name);
|
|
71
85
|
port['off' in port ? 'off' : 'removeEventListener']('message', (message) => {
|
|
72
86
|
handler(typeof message == 'object' && message !== null && 'data' in message ? message.data : message);
|
|
@@ -110,7 +124,12 @@ export class PortFS extends Async(FileSystem) {
|
|
|
110
124
|
constructor(options) {
|
|
111
125
|
super(0x706f7274, 'portfs');
|
|
112
126
|
this.options = options;
|
|
113
|
-
|
|
127
|
+
/**
|
|
128
|
+
* A map of outstanding RPC requests
|
|
129
|
+
* @internal @hidden
|
|
130
|
+
*/
|
|
131
|
+
this._executors = new Map();
|
|
132
|
+
/**
|
|
114
133
|
* @hidden
|
|
115
134
|
*/
|
|
116
135
|
this._sync = InMemory.create({ label: 'tmpfs:port' });
|
|
@@ -131,16 +150,24 @@ export class PortFS extends Async(FileSystem) {
|
|
|
131
150
|
return this.rpc('rename', oldPath, newPath);
|
|
132
151
|
}
|
|
133
152
|
async stat(path) {
|
|
134
|
-
|
|
153
|
+
const result = await this.rpc('stat', path);
|
|
154
|
+
return result instanceof Inode ? result : new Inode(result);
|
|
135
155
|
}
|
|
136
156
|
async touch(path, metadata) {
|
|
137
|
-
|
|
157
|
+
const inode = metadata instanceof Inode ? metadata : new Inode(metadata);
|
|
158
|
+
await this.rpc('touch', path, new Uint8Array(inode.buffer, inode.byteOffset, inode.byteLength));
|
|
138
159
|
}
|
|
139
|
-
sync(
|
|
140
|
-
|
|
160
|
+
async sync() {
|
|
161
|
+
await this.rpc('sync');
|
|
162
|
+
for (const executor of this._executors.values()) {
|
|
163
|
+
await executor.promise.catch(() => { });
|
|
164
|
+
}
|
|
141
165
|
}
|
|
142
166
|
async createFile(path, options) {
|
|
143
|
-
|
|
167
|
+
if (options instanceof Inode)
|
|
168
|
+
options = options.toJSON();
|
|
169
|
+
const result = await this.rpc('createFile', path, options);
|
|
170
|
+
return result instanceof Inode ? result : new Inode(result);
|
|
144
171
|
}
|
|
145
172
|
unlink(path) {
|
|
146
173
|
return this.rpc('unlink', path);
|
|
@@ -149,7 +176,10 @@ export class PortFS extends Async(FileSystem) {
|
|
|
149
176
|
return this.rpc('rmdir', path);
|
|
150
177
|
}
|
|
151
178
|
async mkdir(path, options) {
|
|
152
|
-
|
|
179
|
+
if (options instanceof Inode)
|
|
180
|
+
options = options.toJSON();
|
|
181
|
+
const result = await this.rpc('mkdir', path, options);
|
|
182
|
+
return result instanceof Inode ? result : new Inode(result);
|
|
153
183
|
}
|
|
154
184
|
readdir(path) {
|
|
155
185
|
return this.rpc('readdir', path);
|
|
@@ -187,8 +217,9 @@ export async function handleRequest(port, fs, request) {
|
|
|
187
217
|
case 'mkdir': {
|
|
188
218
|
__requestMethod(request);
|
|
189
219
|
// @ts-expect-error 2556
|
|
190
|
-
const
|
|
191
|
-
|
|
220
|
+
const md = await fs[request.method](...request.args);
|
|
221
|
+
const inode = md instanceof Inode ? md : new Inode(md);
|
|
222
|
+
value = new Uint8Array(inode.buffer, inode.byteOffset, inode.byteLength);
|
|
192
223
|
break;
|
|
193
224
|
}
|
|
194
225
|
case 'touch': {
|
|
@@ -204,7 +235,7 @@ export async function handleRequest(port, fs, request) {
|
|
|
204
235
|
}
|
|
205
236
|
}
|
|
206
237
|
catch (e) {
|
|
207
|
-
error = e instanceof
|
|
238
|
+
error = e instanceof Exception ? e.toJSON() : pick(e, 'message', 'stack');
|
|
208
239
|
}
|
|
209
240
|
port.postMessage({ _zenfs: true, ...pick(request, 'id', 'method', 'stack'), error, value }, transferList);
|
|
210
241
|
}
|