@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.
Files changed (88) hide show
  1. package/dist/backends/backend.js +6 -5
  2. package/dist/backends/cow.d.ts +2 -2
  3. package/dist/backends/cow.js +39 -58
  4. package/dist/backends/fetch.js +27 -29
  5. package/dist/backends/passthrough.d.ts +2 -3
  6. package/dist/backends/passthrough.js +84 -199
  7. package/dist/backends/port.d.ts +16 -3
  8. package/dist/backends/port.js +61 -30
  9. package/dist/backends/single_buffer.d.ts +52 -46
  10. package/dist/backends/single_buffer.js +462 -219
  11. package/dist/backends/store/fs.d.ts +16 -10
  12. package/dist/backends/store/fs.js +227 -242
  13. package/dist/backends/store/store.d.ts +3 -3
  14. package/dist/backends/store/store.js +11 -10
  15. package/dist/config.d.ts +2 -2
  16. package/dist/config.js +10 -11
  17. package/dist/internal/devices.d.ts +2 -2
  18. package/dist/internal/devices.js +39 -49
  19. package/dist/internal/error.d.ts +9 -204
  20. package/dist/internal/error.js +19 -288
  21. package/dist/internal/file_index.d.ts +1 -1
  22. package/dist/internal/file_index.js +9 -9
  23. package/dist/internal/filesystem.d.ts +23 -8
  24. package/dist/internal/index.d.ts +1 -1
  25. package/dist/internal/index.js +1 -1
  26. package/dist/internal/index_fs.d.ts +2 -2
  27. package/dist/internal/index_fs.js +19 -19
  28. package/dist/internal/inode.d.ts +81 -103
  29. package/dist/internal/inode.js +336 -195
  30. package/dist/mixins/async.js +32 -28
  31. package/dist/mixins/mutexed.d.ts +4 -4
  32. package/dist/mixins/mutexed.js +39 -39
  33. package/dist/mixins/readonly.d.ts +2 -2
  34. package/dist/mixins/readonly.js +20 -20
  35. package/dist/mixins/sync.js +2 -2
  36. package/dist/polyfills.js +1 -1
  37. package/dist/readline.js +1 -1
  38. package/dist/utils.d.ts +8 -5
  39. package/dist/utils.js +14 -17
  40. package/dist/vfs/acl.d.ts +8 -8
  41. package/dist/vfs/acl.js +66 -47
  42. package/dist/vfs/async.d.ts +2 -2
  43. package/dist/vfs/async.js +6 -8
  44. package/dist/vfs/dir.d.ts +1 -1
  45. package/dist/vfs/dir.js +3 -4
  46. package/dist/vfs/file.js +33 -24
  47. package/dist/vfs/flags.js +3 -3
  48. package/dist/vfs/ioctl.d.ts +8 -7
  49. package/dist/vfs/ioctl.js +132 -27
  50. package/dist/vfs/promises.d.ts +3 -3
  51. package/dist/vfs/promises.js +200 -235
  52. package/dist/vfs/shared.d.ts +1 -12
  53. package/dist/vfs/shared.js +7 -35
  54. package/dist/vfs/streams.js +9 -9
  55. package/dist/vfs/sync.d.ts +1 -2
  56. package/dist/vfs/sync.js +158 -170
  57. package/dist/vfs/watchers.js +8 -8
  58. package/dist/vfs/xattr.js +89 -106
  59. package/package.json +5 -3
  60. package/scripts/test.js +2 -2
  61. package/tests/assignment.ts +1 -1
  62. package/tests/backend/port.test.ts +4 -4
  63. package/tests/backend/single-buffer.test.ts +39 -10
  64. package/tests/backend/single-buffer.worker.js +30 -0
  65. package/tests/common/context.test.ts +2 -2
  66. package/tests/common/mutex.test.ts +9 -9
  67. package/tests/fetch/fetch.ts +1 -1
  68. package/tests/fetch/run.sh +1 -1
  69. package/tests/fs/append.test.ts +4 -4
  70. package/tests/fs/directory.test.ts +25 -25
  71. package/tests/fs/errors.test.ts +15 -19
  72. package/tests/fs/links.test.ts +3 -2
  73. package/tests/fs/open.test.ts +4 -21
  74. package/tests/fs/permissions.test.ts +8 -13
  75. package/tests/fs/read.test.ts +10 -9
  76. package/tests/fs/readFile.test.ts +8 -24
  77. package/tests/fs/rename.test.ts +4 -9
  78. package/tests/fs/stat.test.ts +2 -2
  79. package/tests/fs/times.test.ts +6 -6
  80. package/tests/fs/truncate.test.ts +8 -36
  81. package/tests/fs/watch.test.ts +10 -10
  82. package/tests/fs/write.test.ts +77 -13
  83. package/tests/fs/xattr.test.ts +7 -7
  84. package/tests/logs.js +2 -2
  85. package/tests/setup/port.ts +6 -0
  86. package/dist/internal/log.d.ts +0 -139
  87. package/dist/internal/log.js +0 -219
  88. 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 { ErrnoError } from '../internal/error.js';
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
- try {
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
- try {
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
- try {
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
- try {
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 env_1 = { stack: [], error: void 0, hasError: false };
125
- try {
126
- const handle = __addDisposableResource(env_1, await this.nodeFS.promises.open(this.path(path), 'w'), true);
127
- await handle.chmod(metadata.mode);
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 (err) {
142
- this.error(err, path);
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
- try {
147
- this.nodeFS.chmodSync(this.path(path), metadata.mode);
148
- this.nodeFS.chownSync(this.path(path), metadata.uid, metadata.gid);
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
- try {
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
- try {
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
- try {
182
- await this.nodeFS.promises.mkdir(this.path(path), options);
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
- try {
194
- this.nodeFS.mkdirSync(this.path(path), options);
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
- try {
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
- try {
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
- try {
228
- if (isDirectory(options)) {
229
- await this.nodeFS.promises.mkdir(this.path(path), { mode: options.mode });
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
- else {
232
- const env_2 = { stack: [], error: void 0, hasError: false };
233
- try {
234
- const handle = __addDisposableResource(env_2, await this.nodeFS.promises.open(this.path(path), 'wx'), true);
235
- await handle.close();
236
- }
237
- catch (e_2) {
238
- env_2.error = e_2;
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
- try {
258
- if (isDirectory(options)) {
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
- catch (err) {
268
- this.error(err, path);
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
- try {
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
- try {
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(path) {
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(path) {
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
- try {
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
- try {
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 env_3 = { stack: [], error: void 0, hasError: false };
330
- try {
331
- const handle = __addDisposableResource(env_3, await this.nodeFS.promises.open(this.path(path), 'r'), true);
332
- await handle.read({ buffer, offset, length: end - offset });
333
- }
334
- catch (e_3) {
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
- catch (err) {
345
- this.error(err, path);
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
- let fd;
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
- if (fd)
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 env_4 = { stack: [], error: void 0, hasError: false };
365
- try {
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 (err) {
380
- this.error(err, path);
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
- let fd;
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
- if (fd)
394
- this.nodeFS.closeSync(fd);
279
+ this.nodeFS.closeSync(fd);
395
280
  }
396
281
  }
397
282
  }
@@ -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(path: string): void;
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(path: string): Promise<void>;
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>;
@@ -1,9 +1,9 @@
1
- import { pick, serialize } from 'utilium';
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(new ErrnoError(Errno.EINVAL, 'Can not make an RPC request without a port'));
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
- executors.set(id, { resolve, reject, promise, fs });
22
- port.postMessage({ ...request, _zenfs: true, id, stack });
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
- if (typeof _ == 'object')
30
- _.unref();
31
- }, timeout);
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(new ErrnoError(Errno.EIO, 'Invalid RPC id:' + response.id));
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 = ErrnoError.fromJSON({ code: 'EIO', errno: Errno.EIO, ...response.error });
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(new ErrnoError(Errno.EINVAL, 'Cannot attach to non-existent port'));
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(new ErrnoError(Errno.EINVAL, 'Cannot detach from non-existent port'));
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
- return new Inode(await this.rpc('stat', path));
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
- await this.rpc('touch', path, serialize(metadata instanceof Inode ? metadata : new Inode(metadata)));
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(path) {
140
- return this.rpc('sync', path);
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
- return new Inode(await this.rpc('createFile', path, options));
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
- return new Inode(await this.rpc('mkdir', path, options));
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 inode = await fs[request.method](...request.args);
191
- value = serialize(inode instanceof Inode ? inode : new Inode(inode));
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 ErrnoError ? e.toJSON() : pick(e, 'message', 'stack');
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
  }