@poe-platform/safe-fs 0.1.730 → 0.1.731
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.
|
@@ -69,6 +69,7 @@ export declare class MemoryFileSystem implements FileSystem {
|
|
|
69
69
|
private openWrite;
|
|
70
70
|
private writeData;
|
|
71
71
|
private writeAt;
|
|
72
|
+
private writeAtRange;
|
|
72
73
|
writeMemoryFileFast(path: string, data: Uint8Array, append: boolean, mode: number): void;
|
|
73
74
|
writeMemoryFileInDirFast(dirPrefix: string, name: string, data: Uint8Array, append: boolean, mode: number): void;
|
|
74
75
|
readFile(path: string, options?: ReadFileOptions): Promise<Uint8Array>;
|
|
@@ -118,13 +119,15 @@ export declare class MemoryFileSystem implements FileSystem {
|
|
|
118
119
|
}
|
|
119
120
|
export declare function createMemoryFileSystem(options?: MemoryFileSystemOptions | Readonly<Record<string, unknown>>): MemoryFileSystem;
|
|
120
121
|
export declare class MemoryRedirectHandle {
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
122
|
+
fs: MemoryFileSystem;
|
|
123
|
+
path: string;
|
|
124
|
+
node: FileNode;
|
|
125
|
+
append: boolean;
|
|
125
126
|
position: number;
|
|
126
127
|
closed: boolean;
|
|
127
128
|
constructor(fs: MemoryFileSystem, path: string, node: FileNode, append: boolean);
|
|
129
|
+
reset(fs: MemoryFileSystem, path: string, node: FileNode, append: boolean): void;
|
|
130
|
+
writeRangeSync(src: Uint8Array, len: number, signal?: AbortSignal): void;
|
|
128
131
|
writeSync(chunk: Uint8Array, signal?: AbortSignal): void;
|
|
129
132
|
close(): void;
|
|
130
133
|
}
|
|
@@ -16,12 +16,15 @@ import { normalizeMemoryFileSystemLimits } from "./limits.js";
|
|
|
16
16
|
export { defaultMemoryFileSystemLimits } from "./limits.js";
|
|
17
17
|
class MemoryFileNode {
|
|
18
18
|
constructor(mode, ino, now, byteLength, allocation, view) {
|
|
19
|
+
this.revision = 0;
|
|
19
20
|
this.mode = mode;
|
|
20
21
|
this.ino = ino;
|
|
22
|
+
this.nlink = 1;
|
|
21
23
|
this.atimeMs = now;
|
|
22
24
|
this.mtimeMs = now;
|
|
23
25
|
this.ctimeMs = now;
|
|
24
26
|
this.birthtimeMs = now;
|
|
27
|
+
this.references = 0;
|
|
25
28
|
this.byteLength = byteLength;
|
|
26
29
|
this.allocation = allocation;
|
|
27
30
|
this.view = view;
|
|
@@ -46,19 +49,216 @@ let smallAllocSlab = new Uint8Array(SMALL_ALLOC_SLAB_SIZE);
|
|
|
46
49
|
let smallAllocOffset = 0;
|
|
47
50
|
const DUMMY_POOL_LEDGER = new MemoryLedger(normalizeMemoryFileSystemLimits({}));
|
|
48
51
|
const DUMMY_POOL_ALLOCATION = new MemoryAllocation(EMPTY_ALLOC_BYTES, DUMMY_POOL_LEDGER);
|
|
49
|
-
const
|
|
50
|
-
|
|
51
|
-
const
|
|
52
|
-
|
|
52
|
+
const DUMMY_POOL_FILE_NODE = new MemoryFileNode(0, 0, null, 0, DUMMY_POOL_ALLOCATION, DUMMY_POOL_ALLOCATION.data);
|
|
53
|
+
DUMMY_POOL_FILE_NODE.atimeMs = DUMMY_POOL_FILE_NODE.mtimeMs = DUMMY_POOL_FILE_NODE.ctimeMs = DUMMY_POOL_FILE_NODE.birthtimeMs = 1700000000000;
|
|
54
|
+
const defaultDateNow = Date.now;
|
|
55
|
+
let fastWriteCachedNow = Date.now();
|
|
56
|
+
let fastWriteNowTick = 0;
|
|
57
|
+
class FastDirectoryEntriesMap {
|
|
58
|
+
_table = new Int16Array(128).fill(-1);
|
|
59
|
+
_mask = 127;
|
|
60
|
+
_keys = new Array(64).fill("");
|
|
61
|
+
_vals = new Array(64).fill(DUMMY_POOL_FILE_NODE);
|
|
62
|
+
_next = 0;
|
|
63
|
+
size = 0;
|
|
64
|
+
[Symbol.toStringTag] = "Map";
|
|
65
|
+
_hash(k) {
|
|
66
|
+
let h = 5381;
|
|
67
|
+
for (let i = 0; i < k.length; i++) {
|
|
68
|
+
h = (((h & 0x1fffff) * 33) ^ k.charCodeAt(i)) & 0x3fffffff;
|
|
69
|
+
}
|
|
70
|
+
return h & this._mask;
|
|
71
|
+
}
|
|
72
|
+
get(k) {
|
|
73
|
+
if (this.size === 0)
|
|
74
|
+
return undefined;
|
|
75
|
+
let slot = this._hash(k);
|
|
76
|
+
const mask = this._mask;
|
|
77
|
+
const table = this._table;
|
|
78
|
+
const keys = this._keys;
|
|
79
|
+
while (true) {
|
|
80
|
+
const idx = table[slot];
|
|
81
|
+
if (idx === -1)
|
|
82
|
+
return undefined;
|
|
83
|
+
if (idx >= 0 && keys[idx] === k)
|
|
84
|
+
return this._vals[idx];
|
|
85
|
+
slot = (slot + 1) & mask;
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
has(k) {
|
|
89
|
+
return this.get(k) !== undefined;
|
|
90
|
+
}
|
|
91
|
+
_rebuild(newCap) {
|
|
92
|
+
const newTableLen = newCap * 2;
|
|
93
|
+
const newMask = newTableLen - 1;
|
|
94
|
+
const newTable = newCap <= 16384 ? new Int16Array(newTableLen).fill(-1) : new Int32Array(newTableLen).fill(-1);
|
|
95
|
+
const oldKeys = this._keys;
|
|
96
|
+
const oldVals = this._vals;
|
|
97
|
+
const oldNext = this._next;
|
|
98
|
+
const newKeys = newCap === oldKeys.length ? oldKeys : new Array(newCap).fill("");
|
|
99
|
+
const newVals = newCap === oldVals.length ? oldVals : new Array(newCap).fill(DUMMY_POOL_FILE_NODE);
|
|
100
|
+
let writeIdx = 0;
|
|
101
|
+
for (let i = 0; i < oldNext; i++) {
|
|
102
|
+
const v = oldVals[i];
|
|
103
|
+
if (v === DUMMY_POOL_FILE_NODE)
|
|
104
|
+
continue;
|
|
105
|
+
const k = oldKeys[i];
|
|
106
|
+
newKeys[writeIdx] = k;
|
|
107
|
+
newVals[writeIdx] = v;
|
|
108
|
+
let h = 5381;
|
|
109
|
+
for (let c = 0; c < k.length; c++) {
|
|
110
|
+
h = (((h & 0x1fffff) * 33) ^ k.charCodeAt(c)) & 0x3fffffff;
|
|
111
|
+
}
|
|
112
|
+
let slot = h & newMask;
|
|
113
|
+
while (newTable[slot] !== -1) {
|
|
114
|
+
slot = (slot + 1) & newMask;
|
|
115
|
+
}
|
|
116
|
+
newTable[slot] = writeIdx++;
|
|
117
|
+
}
|
|
118
|
+
if (newKeys === oldKeys) {
|
|
119
|
+
for (let i = writeIdx; i < oldNext; i++) {
|
|
120
|
+
newKeys[i] = "";
|
|
121
|
+
newVals[i] = DUMMY_POOL_FILE_NODE;
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
this._table = newTable;
|
|
125
|
+
this._mask = newMask;
|
|
126
|
+
this._keys = newKeys;
|
|
127
|
+
this._vals = newVals;
|
|
128
|
+
this._next = writeIdx;
|
|
129
|
+
}
|
|
130
|
+
set(k, v) {
|
|
131
|
+
if (this._next >= this._keys.length) {
|
|
132
|
+
this._rebuild(this.size * 2 <= this._keys.length ? this._keys.length : this._keys.length * 2);
|
|
133
|
+
}
|
|
134
|
+
let slot = this._hash(k);
|
|
135
|
+
const mask = this._mask;
|
|
136
|
+
const table = this._table;
|
|
137
|
+
const keys = this._keys;
|
|
138
|
+
let firstDeleted = -1;
|
|
139
|
+
while (true) {
|
|
140
|
+
const idx = table[slot];
|
|
141
|
+
if (idx === -1) {
|
|
142
|
+
const targetSlot = firstDeleted !== -1 ? firstDeleted : slot;
|
|
143
|
+
const entryIdx = this._next++;
|
|
144
|
+
table[targetSlot] = entryIdx;
|
|
145
|
+
keys[entryIdx] = k;
|
|
146
|
+
this._vals[entryIdx] = v;
|
|
147
|
+
this.size++;
|
|
148
|
+
return this;
|
|
149
|
+
}
|
|
150
|
+
if (idx === -2) {
|
|
151
|
+
if (firstDeleted === -1)
|
|
152
|
+
firstDeleted = slot;
|
|
153
|
+
}
|
|
154
|
+
else if (keys[idx] === k) {
|
|
155
|
+
this._vals[idx] = v;
|
|
156
|
+
return this;
|
|
157
|
+
}
|
|
158
|
+
slot = (slot + 1) & mask;
|
|
159
|
+
}
|
|
160
|
+
}
|
|
161
|
+
delete(k) {
|
|
162
|
+
if (this.size === 0)
|
|
163
|
+
return false;
|
|
164
|
+
let slot = this._hash(k);
|
|
165
|
+
const mask = this._mask;
|
|
166
|
+
const table = this._table;
|
|
167
|
+
const keys = this._keys;
|
|
168
|
+
while (true) {
|
|
169
|
+
const idx = table[slot];
|
|
170
|
+
if (idx === -1)
|
|
171
|
+
return false;
|
|
172
|
+
if (idx >= 0 && keys[idx] === k) {
|
|
173
|
+
if (this.size === 1) {
|
|
174
|
+
this.clear();
|
|
175
|
+
return true;
|
|
176
|
+
}
|
|
177
|
+
table[slot] = -2;
|
|
178
|
+
keys[idx] = "";
|
|
179
|
+
this._vals[idx] = DUMMY_POOL_FILE_NODE;
|
|
180
|
+
if (idx === this._next - 1)
|
|
181
|
+
this._next--;
|
|
182
|
+
this.size--;
|
|
183
|
+
return true;
|
|
184
|
+
}
|
|
185
|
+
slot = (slot + 1) & mask;
|
|
186
|
+
}
|
|
187
|
+
}
|
|
188
|
+
clear() {
|
|
189
|
+
if (this._next > 0) {
|
|
190
|
+
this._table.fill(-1);
|
|
191
|
+
for (let i = 0; i < this._next; i++) {
|
|
192
|
+
this._keys[i] = "";
|
|
193
|
+
this._vals[i] = DUMMY_POOL_FILE_NODE;
|
|
194
|
+
}
|
|
195
|
+
this._next = 0;
|
|
196
|
+
this.size = 0;
|
|
197
|
+
}
|
|
198
|
+
}
|
|
199
|
+
forEach(callbackfn, thisArg) {
|
|
200
|
+
const next = this._next;
|
|
201
|
+
const keys = this._keys;
|
|
202
|
+
const vals = this._vals;
|
|
203
|
+
for (let i = 0; i < next; i++) {
|
|
204
|
+
const v = vals[i];
|
|
205
|
+
if (v !== DUMMY_POOL_FILE_NODE) {
|
|
206
|
+
if (thisArg !== undefined)
|
|
207
|
+
callbackfn.call(thisArg, v, keys[i], this);
|
|
208
|
+
else
|
|
209
|
+
callbackfn(v, keys[i], this);
|
|
210
|
+
}
|
|
211
|
+
}
|
|
212
|
+
}
|
|
213
|
+
*keys() {
|
|
214
|
+
for (let i = 0; i < this._next; i++) {
|
|
215
|
+
if (this._vals[i] !== DUMMY_POOL_FILE_NODE)
|
|
216
|
+
yield this._keys[i];
|
|
217
|
+
}
|
|
218
|
+
}
|
|
219
|
+
*values() {
|
|
220
|
+
for (let i = 0; i < this._next; i++) {
|
|
221
|
+
const v = this._vals[i];
|
|
222
|
+
if (v !== DUMMY_POOL_FILE_NODE)
|
|
223
|
+
yield v;
|
|
224
|
+
}
|
|
225
|
+
}
|
|
226
|
+
*entries() {
|
|
227
|
+
for (let i = 0; i < this._next; i++) {
|
|
228
|
+
const v = this._vals[i];
|
|
229
|
+
if (v !== DUMMY_POOL_FILE_NODE)
|
|
230
|
+
yield [this._keys[i], v];
|
|
231
|
+
}
|
|
232
|
+
}
|
|
233
|
+
[Symbol.iterator]() {
|
|
234
|
+
return this.entries();
|
|
235
|
+
}
|
|
236
|
+
}
|
|
237
|
+
const SHARED_POOL_CAPACITY = 256;
|
|
238
|
+
const SHARED_DIR_POOL_CAPACITY = 64;
|
|
239
|
+
const sharedAllocationPool = new Array(SHARED_POOL_CAPACITY).fill(DUMMY_POOL_ALLOCATION);
|
|
240
|
+
let sharedAllocationPoolLen = 0;
|
|
241
|
+
const sharedFileNodePool = new Array(SHARED_POOL_CAPACITY).fill(DUMMY_POOL_FILE_NODE);
|
|
242
|
+
let sharedFileNodePoolLen = 0;
|
|
243
|
+
const sharedDirectoryNodePool = new Array(SHARED_DIR_POOL_CAPACITY);
|
|
244
|
+
let sharedDirectoryNodePoolLen = 0;
|
|
245
|
+
const sharedRemovedScratch = new Array(SHARED_POOL_CAPACITY).fill(DUMMY_POOL_FILE_NODE);
|
|
246
|
+
let sharedRemovedLen = 0;
|
|
53
247
|
let sharedRemovedKeyChars = 0;
|
|
54
248
|
let sharedRemovedKeyEntries = 0;
|
|
55
249
|
function collectRemovedChild(child, name) {
|
|
56
|
-
sharedRemovedScratch.
|
|
250
|
+
if (sharedRemovedLen < sharedRemovedScratch.length) {
|
|
251
|
+
sharedRemovedScratch[sharedRemovedLen++] = child;
|
|
252
|
+
}
|
|
253
|
+
else {
|
|
254
|
+
sharedRemovedScratch.push(child);
|
|
255
|
+
sharedRemovedLen++;
|
|
256
|
+
}
|
|
57
257
|
sharedRemovedKeyChars += name.length;
|
|
58
258
|
sharedRemovedKeyEntries++;
|
|
59
259
|
}
|
|
60
260
|
function replenishSharedMemoryPools() {
|
|
61
|
-
while (
|
|
261
|
+
while (sharedAllocationPoolLen < 112) {
|
|
62
262
|
if (smallAllocOffset + 64 > SMALL_ALLOC_SLAB_SIZE) {
|
|
63
263
|
smallAllocSlab = new Uint8Array(SMALL_ALLOC_SLAB_SIZE);
|
|
64
264
|
smallAllocOffset = 0;
|
|
@@ -68,24 +268,29 @@ function replenishSharedMemoryPools() {
|
|
|
68
268
|
DUMMY_POOL_LEDGER.reserve(64, 0, "init", "/");
|
|
69
269
|
const alloc = new MemoryAllocation(slice, DUMMY_POOL_LEDGER);
|
|
70
270
|
alloc.release();
|
|
71
|
-
sharedAllocationPool
|
|
271
|
+
sharedAllocationPool[sharedAllocationPoolLen++] = alloc;
|
|
72
272
|
}
|
|
73
|
-
while (
|
|
74
|
-
sharedFileNodePool
|
|
273
|
+
while (sharedFileNodePoolLen < 112) {
|
|
274
|
+
sharedFileNodePool[sharedFileNodePoolLen++] = new MemoryFileNode(0, 0, fastWriteCachedNow, 0, DUMMY_POOL_ALLOCATION, undefined);
|
|
75
275
|
}
|
|
76
|
-
while (
|
|
77
|
-
sharedDirectoryNodePool
|
|
276
|
+
while (sharedDirectoryNodePoolLen < 16) {
|
|
277
|
+
sharedDirectoryNodePool[sharedDirectoryNodePoolLen++] = new MemoryDirectoryNode(0, 0, fastWriteCachedNow);
|
|
78
278
|
}
|
|
79
279
|
}
|
|
80
280
|
class MemoryDirectoryNode {
|
|
81
281
|
constructor(mode, ino, now) {
|
|
282
|
+
this.revision = 0;
|
|
82
283
|
this.mode = mode;
|
|
83
284
|
this.ino = ino;
|
|
285
|
+
this.nlink = 1;
|
|
286
|
+
this.references = 0;
|
|
84
287
|
this.atimeMs = now;
|
|
85
288
|
this.mtimeMs = now;
|
|
86
289
|
this.ctimeMs = now;
|
|
87
290
|
this.birthtimeMs = now;
|
|
88
|
-
this.entries = new
|
|
291
|
+
this.entries = new FastDirectoryEntriesMap();
|
|
292
|
+
this.cachedNlink = 2;
|
|
293
|
+
this.cachedNlinkRev = 0;
|
|
89
294
|
}
|
|
90
295
|
}
|
|
91
296
|
Object.assign(MemoryDirectoryNode.prototype, {
|
|
@@ -96,6 +301,8 @@ Object.assign(MemoryDirectoryNode.prototype, {
|
|
|
96
301
|
cachedNlink: 2,
|
|
97
302
|
cachedNlinkRev: 0,
|
|
98
303
|
});
|
|
304
|
+
const DUMMY_POOL_DIR_NODE = new MemoryDirectoryNode(0, 0, null);
|
|
305
|
+
DUMMY_POOL_DIR_NODE.atimeMs = DUMMY_POOL_DIR_NODE.mtimeMs = DUMMY_POOL_DIR_NODE.ctimeMs = DUMMY_POOL_DIR_NODE.birthtimeMs = 1700000000000;
|
|
99
306
|
class MemoryCache {
|
|
100
307
|
allocations = [];
|
|
101
308
|
files = [];
|
|
@@ -117,6 +324,9 @@ class MemoryCache {
|
|
|
117
324
|
const typeModes = { file: 0o100000, directory: 0o040000, symlink: 0o120000 };
|
|
118
325
|
const emptyResolveOptions = Object.freeze({});
|
|
119
326
|
const noFollowResolveOptions = Object.freeze({ followFinal: false });
|
|
327
|
+
const sharedMkdirResolveOptions = { createDirectories: 0o777 };
|
|
328
|
+
const sharedAllowMissingNoFollowOptions = Object.freeze({ allowMissing: true, followFinal: false });
|
|
329
|
+
const sharedFastLocation = { node: undefined, parent: DUMMY_POOL_DIR_NODE, name: "", path: "" };
|
|
120
330
|
const resolvedVoid = Promise.resolve();
|
|
121
331
|
const preferredIoBlockSize = 64 * 1024;
|
|
122
332
|
const ext4HtreeEof64 = (1n << 63n) - 1n;
|
|
@@ -496,11 +706,17 @@ export class MemoryFileSystem {
|
|
|
496
706
|
atimeMs: now, mtimeMs: now, ctimeMs: now, birthtimeMs: now,
|
|
497
707
|
};
|
|
498
708
|
}
|
|
499
|
-
directory(mode) {
|
|
500
|
-
const now = Date.now();
|
|
709
|
+
directory(mode, now = Date.now()) {
|
|
501
710
|
const fullMode = typeModes.directory | mode;
|
|
502
711
|
const ino = this.nextInode++;
|
|
503
|
-
|
|
712
|
+
let pooled;
|
|
713
|
+
if (sharedDirectoryNodePoolLen > 0) {
|
|
714
|
+
pooled = sharedDirectoryNodePool[--sharedDirectoryNodePoolLen];
|
|
715
|
+
sharedDirectoryNodePool[sharedDirectoryNodePoolLen] = DUMMY_POOL_DIR_NODE;
|
|
716
|
+
}
|
|
717
|
+
else {
|
|
718
|
+
pooled = memoryCaches.get(this.ledger)?.directories.pop();
|
|
719
|
+
}
|
|
504
720
|
if (pooled) {
|
|
505
721
|
pooled.mode = fullMode;
|
|
506
722
|
pooled.ino = ino;
|
|
@@ -517,13 +733,13 @@ export class MemoryFileSystem {
|
|
|
517
733
|
}
|
|
518
734
|
return new MemoryDirectoryNode(fullMode, ino, now);
|
|
519
735
|
}
|
|
520
|
-
addDirectoryNode(parent, name, mode, syscall, path) {
|
|
736
|
+
addDirectoryNode(parent, name, mode, syscall, path, now = Date.now()) {
|
|
521
737
|
const bytes = name.length * 2;
|
|
522
738
|
this.ledger.reserve(bytes, 2, syscall, path);
|
|
523
739
|
try {
|
|
524
|
-
const node = this.directory(mode);
|
|
740
|
+
const node = this.directory(mode, now);
|
|
525
741
|
parent.entries.set(name, node);
|
|
526
|
-
this.changed(parent);
|
|
742
|
+
this.changed(parent, now);
|
|
527
743
|
return node;
|
|
528
744
|
}
|
|
529
745
|
catch (error) {
|
|
@@ -569,15 +785,15 @@ export class MemoryFileSystem {
|
|
|
569
785
|
alloc.release();
|
|
570
786
|
if (alloc.isReleased64()) {
|
|
571
787
|
alloc.detachLedger(DUMMY_POOL_LEDGER);
|
|
572
|
-
if (this.ledger.hasInfiniteRetained && this.ledger.limits.maxFileBytes === Infinity &&
|
|
573
|
-
sharedAllocationPool
|
|
788
|
+
if (this.ledger.hasInfiniteRetained && this.ledger.limits.maxFileBytes === Infinity && sharedAllocationPoolLen < SHARED_POOL_CAPACITY) {
|
|
789
|
+
sharedAllocationPool[sharedAllocationPoolLen++] = alloc;
|
|
574
790
|
}
|
|
575
791
|
else if (cache.allocations.length < 128) {
|
|
576
792
|
cache.allocations.push(alloc);
|
|
577
793
|
}
|
|
578
794
|
}
|
|
579
|
-
if (
|
|
580
|
-
sharedFileNodePool
|
|
795
|
+
if (sharedFileNodePoolLen < SHARED_POOL_CAPACITY) {
|
|
796
|
+
sharedFileNodePool[sharedFileNodePoolLen++] = node;
|
|
581
797
|
}
|
|
582
798
|
else if (cache.files.length < 128) {
|
|
583
799
|
cache.files.push(node);
|
|
@@ -592,8 +808,8 @@ export class MemoryFileSystem {
|
|
|
592
808
|
cache.lastFastDirNode = undefined;
|
|
593
809
|
}
|
|
594
810
|
if (node.entries.size === 0) {
|
|
595
|
-
if (
|
|
596
|
-
sharedDirectoryNodePool
|
|
811
|
+
if (sharedDirectoryNodePoolLen < SHARED_DIR_POOL_CAPACITY) {
|
|
812
|
+
sharedDirectoryNodePool[sharedDirectoryNodePoolLen++] = node;
|
|
597
813
|
}
|
|
598
814
|
else if (cache.directories.length < 32) {
|
|
599
815
|
cache.directories.push(node);
|
|
@@ -967,12 +1183,17 @@ export class MemoryFileSystem {
|
|
|
967
1183
|
this.ledger.fileSize(length, syscall, path);
|
|
968
1184
|
this.ledger.reserve(length, 0, syscall, path);
|
|
969
1185
|
if (length === 0) {
|
|
970
|
-
return
|
|
1186
|
+
return DUMMY_POOL_ALLOCATION;
|
|
971
1187
|
}
|
|
972
1188
|
if (length === 64) {
|
|
973
|
-
|
|
974
|
-
|
|
975
|
-
|
|
1189
|
+
let pooled;
|
|
1190
|
+
if (this.ledger.hasInfiniteRetained && this.ledger.limits.maxFileBytes === Infinity && sharedAllocationPoolLen > 0) {
|
|
1191
|
+
pooled = sharedAllocationPool[--sharedAllocationPoolLen];
|
|
1192
|
+
sharedAllocationPool[sharedAllocationPoolLen] = DUMMY_POOL_ALLOCATION;
|
|
1193
|
+
}
|
|
1194
|
+
else {
|
|
1195
|
+
pooled = memoryCaches.get(this.ledger).allocations.pop();
|
|
1196
|
+
}
|
|
976
1197
|
if (pooled) {
|
|
977
1198
|
pooled.reuse(this.ledger);
|
|
978
1199
|
return pooled;
|
|
@@ -1092,7 +1313,14 @@ export class MemoryFileSystem {
|
|
|
1092
1313
|
const now = Date.now();
|
|
1093
1314
|
const fileMode = typeModes.file | target.mode;
|
|
1094
1315
|
const view = capacity === length ? allocation.data : undefined;
|
|
1095
|
-
|
|
1316
|
+
let pooled;
|
|
1317
|
+
if (sharedFileNodePoolLen > 0) {
|
|
1318
|
+
pooled = sharedFileNodePool[--sharedFileNodePoolLen];
|
|
1319
|
+
sharedFileNodePool[sharedFileNodePoolLen] = DUMMY_POOL_FILE_NODE;
|
|
1320
|
+
}
|
|
1321
|
+
else {
|
|
1322
|
+
pooled = memoryCaches.get(this.ledger).files.pop();
|
|
1323
|
+
}
|
|
1096
1324
|
if (pooled) {
|
|
1097
1325
|
pooled.mode = fileMode;
|
|
1098
1326
|
pooled.ino = this.nextInode++;
|
|
@@ -1128,11 +1356,14 @@ export class MemoryFileSystem {
|
|
|
1128
1356
|
}
|
|
1129
1357
|
}
|
|
1130
1358
|
writeAt(node, data, position, syscall, path) {
|
|
1131
|
-
|
|
1132
|
-
|
|
1359
|
+
this.writeAtRange(node, data, data.byteLength, position, syscall, path, Date.now());
|
|
1360
|
+
}
|
|
1361
|
+
writeAtRange(node, data, dataLen, position, syscall, path, now) {
|
|
1362
|
+
if (dataLen === 0) {
|
|
1363
|
+
this.changed(node, now);
|
|
1133
1364
|
return;
|
|
1134
1365
|
}
|
|
1135
|
-
const end = position +
|
|
1366
|
+
const end = position + dataLen;
|
|
1136
1367
|
this.ledger.fileSize(end, syscall, path);
|
|
1137
1368
|
const curLen = node.byteLength;
|
|
1138
1369
|
const length = Math.max(curLen, end);
|
|
@@ -1151,11 +1382,17 @@ export class MemoryFileSystem {
|
|
|
1151
1382
|
}
|
|
1152
1383
|
try {
|
|
1153
1384
|
const storage = allocation.data;
|
|
1154
|
-
if (allocation !== node.allocation)
|
|
1155
|
-
storage.set(node.
|
|
1385
|
+
if (allocation !== node.allocation && curLen > 0) {
|
|
1386
|
+
storage.set(node.allocation.data.subarray(0, curLen));
|
|
1387
|
+
}
|
|
1156
1388
|
if (position > curLen)
|
|
1157
1389
|
storage.fill(0, curLen, position);
|
|
1158
|
-
|
|
1390
|
+
if (dataLen === data.byteLength) {
|
|
1391
|
+
storage.set(data, position);
|
|
1392
|
+
}
|
|
1393
|
+
else {
|
|
1394
|
+
storage.set(data.subarray(0, dataLen), position);
|
|
1395
|
+
}
|
|
1159
1396
|
}
|
|
1160
1397
|
catch (error) {
|
|
1161
1398
|
if (allocation !== node.allocation)
|
|
@@ -1169,7 +1406,7 @@ export class MemoryFileSystem {
|
|
|
1169
1406
|
node.byteLength = length;
|
|
1170
1407
|
node.view = length === allocation.data.byteLength ? allocation.data : undefined;
|
|
1171
1408
|
}
|
|
1172
|
-
this.changed(node);
|
|
1409
|
+
this.changed(node, now);
|
|
1173
1410
|
}
|
|
1174
1411
|
writeMemoryFileFast(path, data, append, mode) {
|
|
1175
1412
|
const cache = memoryCaches.get(this.ledger);
|
|
@@ -1264,7 +1501,14 @@ export class MemoryFileSystem {
|
|
|
1264
1501
|
const now = Date.now();
|
|
1265
1502
|
const fileMode = typeModes.file | mode;
|
|
1266
1503
|
const view = capacity === length ? allocation.data : undefined;
|
|
1267
|
-
let node
|
|
1504
|
+
let node;
|
|
1505
|
+
if (sharedFileNodePoolLen > 0) {
|
|
1506
|
+
node = sharedFileNodePool[--sharedFileNodePoolLen];
|
|
1507
|
+
sharedFileNodePool[sharedFileNodePoolLen] = DUMMY_POOL_FILE_NODE;
|
|
1508
|
+
}
|
|
1509
|
+
else {
|
|
1510
|
+
node = cache.files.pop();
|
|
1511
|
+
}
|
|
1268
1512
|
if (node) {
|
|
1269
1513
|
node.mode = fileMode;
|
|
1270
1514
|
node.ino = this.nextInode++;
|
|
@@ -1404,16 +1648,26 @@ export class MemoryFileSystem {
|
|
|
1404
1648
|
allocation.data.set(data);
|
|
1405
1649
|
this.ledger.reserve(nameBytes, 2, syscall, name);
|
|
1406
1650
|
try {
|
|
1407
|
-
const now =
|
|
1651
|
+
const now = fastWriteCachedNow;
|
|
1408
1652
|
const fileMode = typeModes.file | mode;
|
|
1409
1653
|
const view = capacity === length ? allocation.data : undefined;
|
|
1410
|
-
let node
|
|
1654
|
+
let node;
|
|
1655
|
+
if (sharedFileNodePoolLen > 0) {
|
|
1656
|
+
node = sharedFileNodePool[--sharedFileNodePoolLen];
|
|
1657
|
+
sharedFileNodePool[sharedFileNodePoolLen] = DUMMY_POOL_FILE_NODE;
|
|
1658
|
+
}
|
|
1659
|
+
else {
|
|
1660
|
+
node = cache.files.pop();
|
|
1661
|
+
}
|
|
1411
1662
|
if (node) {
|
|
1412
1663
|
node.mode = fileMode;
|
|
1413
1664
|
node.ino = this.nextInode++;
|
|
1414
|
-
node.nlink
|
|
1415
|
-
|
|
1416
|
-
node.
|
|
1665
|
+
if (node.nlink !== 1)
|
|
1666
|
+
node.nlink = 1;
|
|
1667
|
+
if (node.references !== 0)
|
|
1668
|
+
node.references = 0;
|
|
1669
|
+
if (node.revision !== 0)
|
|
1670
|
+
node.revision = 0;
|
|
1417
1671
|
node.atimeMs = now;
|
|
1418
1672
|
node.mtimeMs = now;
|
|
1419
1673
|
node.ctimeMs = now;
|
|
@@ -1991,7 +2245,7 @@ export class MemoryFileSystem {
|
|
|
1991
2245
|
return Promise.reject(error);
|
|
1992
2246
|
}
|
|
1993
2247
|
}
|
|
1994
|
-
removeLocation(location, path, syscall, recursive) {
|
|
2248
|
+
removeLocation(location, path, syscall, recursive, now = Date.now()) {
|
|
1995
2249
|
const node = location.node;
|
|
1996
2250
|
if (this.terminalDot(path))
|
|
1997
2251
|
this.fail("EINVAL", syscall, path);
|
|
@@ -2003,12 +2257,12 @@ export class MemoryFileSystem {
|
|
|
2003
2257
|
const cache = memoryCaches.get(this.ledger);
|
|
2004
2258
|
cache.clearWrites();
|
|
2005
2259
|
const removed = sharedRemovedScratch;
|
|
2006
|
-
|
|
2007
|
-
removed
|
|
2260
|
+
sharedRemovedLen = 1;
|
|
2261
|
+
removed[0] = node;
|
|
2008
2262
|
sharedRemovedKeyChars = 0;
|
|
2009
2263
|
sharedRemovedKeyEntries = 0;
|
|
2010
2264
|
try {
|
|
2011
|
-
for (let index = 0; index <
|
|
2265
|
+
for (let index = 0; index < sharedRemovedLen; index++) {
|
|
2012
2266
|
const entry = removed[index];
|
|
2013
2267
|
if (entry.type === "directory" && entry.entries.size > 0) {
|
|
2014
2268
|
this.permission(entry, 7, syscall, path);
|
|
@@ -2017,9 +2271,10 @@ export class MemoryFileSystem {
|
|
|
2017
2271
|
}
|
|
2018
2272
|
location.parent.entries.delete(location.name);
|
|
2019
2273
|
this.ledger.release((location.name.length + sharedRemovedKeyChars) * 2, 1 + sharedRemovedKeyEntries);
|
|
2020
|
-
const
|
|
2021
|
-
for (let i = 0; i <
|
|
2274
|
+
const totalRemoved = sharedRemovedLen;
|
|
2275
|
+
for (let i = 0; i < totalRemoved; i++) {
|
|
2022
2276
|
const entry = removed[i];
|
|
2277
|
+
removed[i] = DUMMY_POOL_FILE_NODE;
|
|
2023
2278
|
if (entry.type === "directory") {
|
|
2024
2279
|
entry.entries.clear();
|
|
2025
2280
|
}
|
|
@@ -2032,9 +2287,11 @@ export class MemoryFileSystem {
|
|
|
2032
2287
|
}
|
|
2033
2288
|
}
|
|
2034
2289
|
finally {
|
|
2035
|
-
|
|
2290
|
+
for (let i = 0; i < sharedRemovedLen; i++)
|
|
2291
|
+
removed[i] = DUMMY_POOL_FILE_NODE;
|
|
2292
|
+
sharedRemovedLen = 0;
|
|
2036
2293
|
}
|
|
2037
|
-
this.changed(location.parent);
|
|
2294
|
+
this.changed(location.parent, now);
|
|
2038
2295
|
}
|
|
2039
2296
|
unlink(path, options = {}) {
|
|
2040
2297
|
// Do not allow an untyped recursive option to widen final-entry removal.
|
|
@@ -2490,24 +2747,46 @@ export class MemoryRedirectHandle {
|
|
|
2490
2747
|
this.position = 0;
|
|
2491
2748
|
this.closed = false;
|
|
2492
2749
|
}
|
|
2493
|
-
|
|
2750
|
+
reset(fs, path, node, append) {
|
|
2751
|
+
this.fs = fs;
|
|
2752
|
+
this.path = path;
|
|
2753
|
+
this.node = node;
|
|
2754
|
+
this.append = append;
|
|
2755
|
+
this.position = 0;
|
|
2756
|
+
this.closed = false;
|
|
2757
|
+
}
|
|
2758
|
+
writeRangeSync(src, len, signal) {
|
|
2494
2759
|
signal?.throwIfAborted();
|
|
2495
2760
|
if (this.closed)
|
|
2496
2761
|
throw new FsError("EBADF", { syscall: "write", path: this.path });
|
|
2497
|
-
if (
|
|
2762
|
+
if (len === 0)
|
|
2498
2763
|
return;
|
|
2499
2764
|
const pos = this.append ? this.node.byteLength : this.position;
|
|
2500
|
-
|
|
2765
|
+
const now = Date.now === defaultDateNow ? fastWriteCachedNow : Date.now();
|
|
2766
|
+
this.fs.writeAtRange(this.node, src, len, pos, "write", this.path, now);
|
|
2501
2767
|
if (!this.append)
|
|
2502
|
-
this.position = pos +
|
|
2768
|
+
this.position = pos + len;
|
|
2769
|
+
}
|
|
2770
|
+
writeSync(chunk, signal) {
|
|
2771
|
+
this.writeRangeSync(chunk, chunk.byteLength, signal);
|
|
2503
2772
|
}
|
|
2504
2773
|
close() {
|
|
2505
2774
|
if (this.closed)
|
|
2506
2775
|
return;
|
|
2507
2776
|
this.closed = true;
|
|
2508
|
-
|
|
2777
|
+
const fs = this.fs;
|
|
2778
|
+
const node = this.node;
|
|
2779
|
+
const path = this.path;
|
|
2780
|
+
this.fs = undefined;
|
|
2781
|
+
this.node = DUMMY_POOL_FILE_NODE;
|
|
2782
|
+
this.path = "";
|
|
2783
|
+
fs.releaseReference(node, path);
|
|
2784
|
+
if (redirectHandlePool.handle === undefined) {
|
|
2785
|
+
redirectHandlePool.handle = this;
|
|
2786
|
+
}
|
|
2509
2787
|
}
|
|
2510
2788
|
}
|
|
2789
|
+
const redirectHandlePool = { handle: undefined };
|
|
2511
2790
|
export function tryOpenMemoryRedirectHandleSync(filesystem, path, append, mode, signal) {
|
|
2512
2791
|
const mem = filesystem;
|
|
2513
2792
|
const owner = ownedStores.get(mem);
|
|
@@ -2517,38 +2796,118 @@ export function tryOpenMemoryRedirectHandleSync(filesystem, path, append, mode,
|
|
|
2517
2796
|
activeConditionalMutations.has(mem.identityScope) ||
|
|
2518
2797
|
!isStockMemoryMethods(mem, openRedirectFastMethodNames, false) ||
|
|
2519
2798
|
!isCleanAbsolutePath(path) ||
|
|
2799
|
+
path === "/" ||
|
|
2520
2800
|
path === "/dev" ||
|
|
2521
2801
|
path.startsWith("/dev/")) {
|
|
2522
2802
|
return undefined;
|
|
2523
2803
|
}
|
|
2524
2804
|
signal?.throwIfAborted();
|
|
2525
|
-
const validMode =
|
|
2526
|
-
|
|
2527
|
-
|
|
2528
|
-
|
|
2529
|
-
|
|
2530
|
-
let
|
|
2531
|
-
|
|
2532
|
-
|
|
2533
|
-
|
|
2534
|
-
|
|
2535
|
-
|
|
2536
|
-
|
|
2537
|
-
|
|
2805
|
+
const validMode = (mode & 0o777) === mode
|
|
2806
|
+
? mode
|
|
2807
|
+
: mem.mode(mode, 0o666, "open", path);
|
|
2808
|
+
const memInternal = mem;
|
|
2809
|
+
let parent = memInternal.root;
|
|
2810
|
+
let start = 1;
|
|
2811
|
+
let name = "";
|
|
2812
|
+
while (true) {
|
|
2813
|
+
memInternal.permission(parent, 1, "open", path);
|
|
2814
|
+
const slash = path.indexOf("/", start);
|
|
2815
|
+
if (slash === -1) {
|
|
2816
|
+
name = path.slice(start);
|
|
2817
|
+
if (exceedsComponentByteLimit(name))
|
|
2818
|
+
memInternal.fail("ENAMETOOLONG", "open", path);
|
|
2819
|
+
break;
|
|
2820
|
+
}
|
|
2821
|
+
const seg = path.slice(start, slash);
|
|
2822
|
+
if (exceedsComponentByteLimit(seg))
|
|
2823
|
+
memInternal.fail("ENAMETOOLONG", "open", path);
|
|
2824
|
+
const next = parent.entries.get(seg);
|
|
2825
|
+
if (!next)
|
|
2826
|
+
memInternal.fail("ENOENT", "open", path);
|
|
2827
|
+
if (next.type !== "directory")
|
|
2828
|
+
memInternal.fail("ENOTDIR", "open", path);
|
|
2829
|
+
parent = next;
|
|
2830
|
+
start = slash + 1;
|
|
2538
2831
|
}
|
|
2539
|
-
const
|
|
2540
|
-
ledger
|
|
2541
|
-
|
|
2542
|
-
|
|
2832
|
+
const existing = parent.entries.get(name);
|
|
2833
|
+
const ledger = memInternal.ledger;
|
|
2834
|
+
let node;
|
|
2835
|
+
if (existing !== undefined) {
|
|
2836
|
+
if (existing.type !== "file")
|
|
2837
|
+
memInternal.fail("EISDIR", "open", path);
|
|
2838
|
+
memInternal.permission(existing, 2, "open", path);
|
|
2839
|
+
ledger.reserve(path.length * 2, 1, "open", path);
|
|
2840
|
+
node = existing;
|
|
2543
2841
|
if (!append) {
|
|
2544
|
-
|
|
2842
|
+
try {
|
|
2843
|
+
memInternal.resizeNode(node, 0, "open", path);
|
|
2844
|
+
}
|
|
2845
|
+
catch (error) {
|
|
2846
|
+
ledger.release(path.length * 2, 1);
|
|
2847
|
+
throw error;
|
|
2848
|
+
}
|
|
2849
|
+
}
|
|
2850
|
+
node.references++;
|
|
2851
|
+
}
|
|
2852
|
+
else {
|
|
2853
|
+
memInternal.permission(parent, 3, "open", path);
|
|
2854
|
+
const refBytes = path.length * 2;
|
|
2855
|
+
const nameBytes = name.length * 2;
|
|
2856
|
+
ledger.reserve(refBytes, 1, "open", path);
|
|
2857
|
+
try {
|
|
2858
|
+
ledger.fileSize(0, "open", path);
|
|
2859
|
+
ledger.reserve(nameBytes, 2, "open", path);
|
|
2860
|
+
}
|
|
2861
|
+
catch (error) {
|
|
2862
|
+
ledger.release(refBytes, 1);
|
|
2863
|
+
throw error;
|
|
2864
|
+
}
|
|
2865
|
+
const cache = memoryCaches.get(ledger);
|
|
2866
|
+
cache.clearWrites();
|
|
2867
|
+
const now = Date.now === defaultDateNow ? ((++fastWriteNowTick & 63) === 0 ? (fastWriteCachedNow = Date.now()) : fastWriteCachedNow) : Date.now();
|
|
2868
|
+
const fileMode = typeModes.file | validMode;
|
|
2869
|
+
let newNode;
|
|
2870
|
+
if (sharedFileNodePoolLen > 0) {
|
|
2871
|
+
newNode = sharedFileNodePool[--sharedFileNodePoolLen];
|
|
2872
|
+
sharedFileNodePool[sharedFileNodePoolLen] = DUMMY_POOL_FILE_NODE;
|
|
2545
2873
|
}
|
|
2874
|
+
else {
|
|
2875
|
+
newNode = cache.files.pop();
|
|
2876
|
+
}
|
|
2877
|
+
if (newNode) {
|
|
2878
|
+
newNode.mode = fileMode;
|
|
2879
|
+
newNode.ino = memInternal.nextInode++;
|
|
2880
|
+
newNode.nlink = 1;
|
|
2881
|
+
newNode.references = 1;
|
|
2882
|
+
newNode.revision = 0;
|
|
2883
|
+
newNode.atimeMs = now;
|
|
2884
|
+
newNode.mtimeMs = now;
|
|
2885
|
+
newNode.ctimeMs = now;
|
|
2886
|
+
newNode.birthtimeMs = now;
|
|
2887
|
+
newNode.byteLength = 0;
|
|
2888
|
+
newNode.view = EMPTY_ALLOC_BYTES;
|
|
2889
|
+
newNode.allocation = DUMMY_POOL_ALLOCATION;
|
|
2890
|
+
}
|
|
2891
|
+
else {
|
|
2892
|
+
newNode = new MemoryFileNode(fileMode, memInternal.nextInode++, now, 0, DUMMY_POOL_ALLOCATION, EMPTY_ALLOC_BYTES);
|
|
2893
|
+
newNode.references = 1;
|
|
2894
|
+
}
|
|
2895
|
+
const prevNlink = parent.cachedNlinkRev === parent.revision ? parent.cachedNlink : (parent.entries.size === 0 ? 2 : undefined);
|
|
2896
|
+
parent.entries.set(name, newNode);
|
|
2897
|
+
parent.revision = parent.revision < 1073741823 ? (parent.revision + 1) | 0 : Math.min(Number.MAX_SAFE_INTEGER + 1, parent.revision + 1);
|
|
2898
|
+
parent.mtimeMs = parent.ctimeMs = now;
|
|
2899
|
+
if (prevNlink !== undefined) {
|
|
2900
|
+
parent.cachedNlink = prevNlink;
|
|
2901
|
+
parent.cachedNlinkRev = parent.revision;
|
|
2902
|
+
}
|
|
2903
|
+
node = newNode;
|
|
2546
2904
|
}
|
|
2547
|
-
|
|
2548
|
-
|
|
2549
|
-
|
|
2905
|
+
const handle = redirectHandlePool.handle;
|
|
2906
|
+
if (handle !== undefined) {
|
|
2907
|
+
redirectHandlePool.handle = undefined;
|
|
2908
|
+
handle.reset(mem, path, node, append);
|
|
2909
|
+
return handle;
|
|
2550
2910
|
}
|
|
2551
|
-
node.references++;
|
|
2552
2911
|
return new MemoryRedirectHandle(mem, path, node, append);
|
|
2553
2912
|
}
|
|
2554
2913
|
export function utf8ByteLength(value) {
|
|
@@ -2686,7 +3045,8 @@ export function tryReadMemoryFileViewSync(filesystem, path, maxBytes, signal) {
|
|
|
2686
3045
|
}
|
|
2687
3046
|
export function tryGetMemoryDirectoryEntryNamesSync(filesystem, path) {
|
|
2688
3047
|
const mem = filesystem;
|
|
2689
|
-
|
|
3048
|
+
const owner = ownedStores.get(mem);
|
|
3049
|
+
if (!owner || mem.symlinkCount !== 0 || !isStockMemoryMethods(mem, readFileFastMethodNames, false))
|
|
2690
3050
|
return undefined;
|
|
2691
3051
|
const root = mem.root;
|
|
2692
3052
|
if (path === "/") {
|
|
@@ -2696,6 +3056,16 @@ export function tryGetMemoryDirectoryEntryNamesSync(filesystem, path) {
|
|
|
2696
3056
|
}
|
|
2697
3057
|
if (!isCleanAbsolutePath(path) || path === "/dev" || path.startsWith("/dev/"))
|
|
2698
3058
|
return undefined;
|
|
3059
|
+
const cache = memoryCaches.get(owner.ledger);
|
|
3060
|
+
const fastDir = cache?.lastFastDirNode;
|
|
3061
|
+
const fastPrefix = cache?.lastFastDirPrefix;
|
|
3062
|
+
if (fastDir !== undefined &&
|
|
3063
|
+
fastDir.nlink !== 0 &&
|
|
3064
|
+
((fastDir.mode >> 6) & 4) === 4 &&
|
|
3065
|
+
fastPrefix !== undefined &&
|
|
3066
|
+
(fastPrefix === path || (fastPrefix.length === path.length + 1 && fastPrefix.charCodeAt(path.length) === 47 && fastPrefix.startsWith(path)))) {
|
|
3067
|
+
return fastDir.entries;
|
|
3068
|
+
}
|
|
2699
3069
|
let current = root;
|
|
2700
3070
|
let start = 1;
|
|
2701
3071
|
while (true) {
|
|
@@ -2746,16 +3116,34 @@ export function tryMkdirMemorySync(filesystem, path, recursive, mode, signal) {
|
|
|
2746
3116
|
signal?.throwIfAborted();
|
|
2747
3117
|
const validMode = mem.mode(mode, 0o777, "mkdir", path);
|
|
2748
3118
|
if (recursive) {
|
|
2749
|
-
|
|
2750
|
-
|
|
2751
|
-
|
|
3119
|
+
let current = owner.root;
|
|
3120
|
+
let start = 1;
|
|
3121
|
+
while (true) {
|
|
3122
|
+
mem.permission(current, 1, "mkdir", path);
|
|
3123
|
+
const slash = path.indexOf("/", start);
|
|
3124
|
+
const seg = slash === -1 ? path.slice(start) : path.slice(start, slash);
|
|
3125
|
+
if (exceedsComponentByteLimit(seg))
|
|
3126
|
+
mem.fail("ENAMETOOLONG", "mkdir", path);
|
|
3127
|
+
let next = current.entries.get(seg);
|
|
3128
|
+
if (!next) {
|
|
3129
|
+
mem.permission(current, 3, "mkdir", path);
|
|
3130
|
+
next = mem.addDirectoryNode(current, seg, validMode, "mkdir", path, fastWriteCachedNow);
|
|
3131
|
+
}
|
|
3132
|
+
else if (next.type !== "directory") {
|
|
3133
|
+
mem.fail(slash === -1 ? "EEXIST" : "ENOTDIR", "mkdir", path);
|
|
3134
|
+
}
|
|
3135
|
+
if (slash === -1)
|
|
3136
|
+
break;
|
|
3137
|
+
current = next;
|
|
3138
|
+
start = slash + 1;
|
|
3139
|
+
}
|
|
2752
3140
|
return true;
|
|
2753
3141
|
}
|
|
2754
|
-
const location = mem.resolve(path, "mkdir",
|
|
3142
|
+
const location = mem.resolve(path, "mkdir", sharedAllowMissingNoFollowOptions);
|
|
2755
3143
|
if (location.node)
|
|
2756
3144
|
mem.fail("EEXIST", "mkdir", path);
|
|
2757
3145
|
mem.permission(location.parent, 3, "mkdir", path);
|
|
2758
|
-
mem.addDirectoryNode(location.parent, location.name, validMode, "mkdir", path);
|
|
3146
|
+
mem.addDirectoryNode(location.parent, location.name, validMode, "mkdir", path, fastWriteCachedNow);
|
|
2759
3147
|
return true;
|
|
2760
3148
|
}
|
|
2761
3149
|
export function tryRmRfMemorySync(filesystem, path, signal) {
|
|
@@ -2772,16 +3160,46 @@ export function tryRmRfMemorySync(filesystem, path, signal) {
|
|
|
2772
3160
|
return false;
|
|
2773
3161
|
}
|
|
2774
3162
|
signal?.throwIfAborted();
|
|
2775
|
-
let
|
|
3163
|
+
let current = owner.root;
|
|
3164
|
+
let start = 1;
|
|
3165
|
+
let targetNode;
|
|
3166
|
+
let targetName = "";
|
|
3167
|
+
while (true) {
|
|
3168
|
+
mem.permission(current, 1, "rm", path);
|
|
3169
|
+
const slash = path.indexOf("/", start);
|
|
3170
|
+
if (slash === -1) {
|
|
3171
|
+
targetName = path.slice(start);
|
|
3172
|
+
if (exceedsComponentByteLimit(targetName))
|
|
3173
|
+
mem.fail("ENAMETOOLONG", "rm", path);
|
|
3174
|
+
targetNode = current.entries.get(targetName);
|
|
3175
|
+
if (!targetNode)
|
|
3176
|
+
return true;
|
|
3177
|
+
break;
|
|
3178
|
+
}
|
|
3179
|
+
const seg = path.slice(start, slash);
|
|
3180
|
+
if (exceedsComponentByteLimit(seg))
|
|
3181
|
+
mem.fail("ENAMETOOLONG", "rm", path);
|
|
3182
|
+
const next = current.entries.get(seg);
|
|
3183
|
+
if (!next)
|
|
3184
|
+
return true;
|
|
3185
|
+
if (next.type !== "directory")
|
|
3186
|
+
mem.fail("ENOTDIR", "rm", path);
|
|
3187
|
+
current = next;
|
|
3188
|
+
start = slash + 1;
|
|
3189
|
+
}
|
|
3190
|
+
sharedFastLocation.node = targetNode;
|
|
3191
|
+
sharedFastLocation.parent = current;
|
|
3192
|
+
sharedFastLocation.name = targetName;
|
|
3193
|
+
sharedFastLocation.path = path;
|
|
2776
3194
|
try {
|
|
2777
|
-
|
|
3195
|
+
mem.removeLocation(sharedFastLocation, path, "rm", true, fastWriteCachedNow);
|
|
2778
3196
|
}
|
|
2779
|
-
|
|
2780
|
-
|
|
2781
|
-
|
|
2782
|
-
|
|
3197
|
+
finally {
|
|
3198
|
+
sharedFastLocation.node = undefined;
|
|
3199
|
+
sharedFastLocation.parent = DUMMY_POOL_DIR_NODE;
|
|
3200
|
+
sharedFastLocation.name = "";
|
|
3201
|
+
sharedFastLocation.path = "";
|
|
2783
3202
|
}
|
|
2784
|
-
mem.removeLocation(location, path, "rm", true);
|
|
2785
3203
|
return true;
|
|
2786
3204
|
}
|
|
2787
3205
|
export function tryWriteMemoryFileInDirSync(filesystem, dirPrefix, name, data, append, mode, signal) {
|
|
@@ -68,13 +68,18 @@ export class MemoryLedger {
|
|
|
68
68
|
}
|
|
69
69
|
export class MemoryAllocation {
|
|
70
70
|
constructor(data, ledger) {
|
|
71
|
+
this.references = 1;
|
|
71
72
|
this.data = data;
|
|
72
73
|
this.ledger = ledger;
|
|
73
74
|
}
|
|
74
75
|
retain() {
|
|
76
|
+
if (this.data.byteLength === 0)
|
|
77
|
+
return;
|
|
75
78
|
this.references++;
|
|
76
79
|
}
|
|
77
80
|
release() {
|
|
81
|
+
if (this.data.byteLength === 0)
|
|
82
|
+
return;
|
|
78
83
|
if (this.references <= 0)
|
|
79
84
|
throw new Error("Memory allocation already released");
|
|
80
85
|
if (--this.references === 0)
|