@componentor/fs 1.2.6 → 1.2.8
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/index.js +133 -69
- package/dist/index.js.map +1 -1
- package/dist/opfs-hybrid.js +133 -69
- package/dist/opfs-hybrid.js.map +1 -1
- package/dist/opfs-worker.js +133 -69
- package/dist/opfs-worker.js.map +1 -1
- package/package.json +1 -1
- package/src/handle-manager.ts +52 -0
- package/src/packed-storage.ts +107 -81
- package/src/symlink-manager.ts +12 -6
package/dist/index.js
CHANGED
|
@@ -145,6 +145,40 @@ function segments(path) {
|
|
|
145
145
|
// src/handle-manager.ts
|
|
146
146
|
var FILE_HANDLE_POOL_SIZE = 50;
|
|
147
147
|
var DIR_CACHE_MAX_SIZE = 200;
|
|
148
|
+
var FileLock = class {
|
|
149
|
+
active = /* @__PURE__ */ new Set();
|
|
150
|
+
queues = /* @__PURE__ */ new Map();
|
|
151
|
+
async acquire(path) {
|
|
152
|
+
if (!this.active.has(path)) {
|
|
153
|
+
this.active.add(path);
|
|
154
|
+
return this.createRelease(path);
|
|
155
|
+
}
|
|
156
|
+
await new Promise((resolve) => {
|
|
157
|
+
let queue = this.queues.get(path);
|
|
158
|
+
if (!queue) {
|
|
159
|
+
queue = [];
|
|
160
|
+
this.queues.set(path, queue);
|
|
161
|
+
}
|
|
162
|
+
queue.push(resolve);
|
|
163
|
+
});
|
|
164
|
+
return this.createRelease(path);
|
|
165
|
+
}
|
|
166
|
+
createRelease(path) {
|
|
167
|
+
return () => {
|
|
168
|
+
const queue = this.queues.get(path);
|
|
169
|
+
if (queue && queue.length > 0) {
|
|
170
|
+
const next = queue.shift();
|
|
171
|
+
if (queue.length === 0) {
|
|
172
|
+
this.queues.delete(path);
|
|
173
|
+
}
|
|
174
|
+
next();
|
|
175
|
+
} else {
|
|
176
|
+
this.active.delete(path);
|
|
177
|
+
}
|
|
178
|
+
};
|
|
179
|
+
}
|
|
180
|
+
};
|
|
181
|
+
var fileLock = new FileLock();
|
|
148
182
|
var HandleManager = class {
|
|
149
183
|
rootPromise;
|
|
150
184
|
dirCache = /* @__PURE__ */ new Map();
|
|
@@ -402,15 +436,20 @@ var SymlinkManager = class {
|
|
|
402
436
|
if (!fileHandle) return;
|
|
403
437
|
const buffer = new TextEncoder().encode(data);
|
|
404
438
|
if (this.useSync) {
|
|
405
|
-
const
|
|
439
|
+
const release = await fileLock.acquire(SYMLINK_FILE);
|
|
406
440
|
try {
|
|
407
|
-
access.
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
441
|
+
const access = await fileHandle.createSyncAccessHandle();
|
|
442
|
+
try {
|
|
443
|
+
access.truncate(0);
|
|
444
|
+
let written = 0;
|
|
445
|
+
while (written < buffer.length) {
|
|
446
|
+
written += access.write(buffer.subarray(written), { at: written });
|
|
447
|
+
}
|
|
448
|
+
} finally {
|
|
449
|
+
access.close();
|
|
411
450
|
}
|
|
412
451
|
} finally {
|
|
413
|
-
|
|
452
|
+
release();
|
|
414
453
|
}
|
|
415
454
|
} else {
|
|
416
455
|
const writable = await fileHandle.createWritable();
|
|
@@ -693,30 +732,35 @@ var PackedStorage = class {
|
|
|
693
732
|
return {};
|
|
694
733
|
}
|
|
695
734
|
if (this.useSync) {
|
|
696
|
-
const
|
|
735
|
+
const release = await fileLock.acquire(PACK_FILE);
|
|
697
736
|
try {
|
|
698
|
-
const
|
|
699
|
-
|
|
700
|
-
|
|
701
|
-
|
|
702
|
-
|
|
703
|
-
access.read(header, { at: 0 });
|
|
704
|
-
const view = new DataView(header.buffer);
|
|
705
|
-
const indexLen = view.getUint32(0, true);
|
|
706
|
-
const storedCrc = view.getUint32(4, true);
|
|
707
|
-
const contentSize = size - 8;
|
|
708
|
-
const content = new Uint8Array(contentSize);
|
|
709
|
-
access.read(content, { at: 8 });
|
|
710
|
-
if (this.useChecksum && storedCrc !== 0) {
|
|
711
|
-
const calculatedCrc = crc32(content);
|
|
712
|
-
if (calculatedCrc !== storedCrc) {
|
|
713
|
-
throw createECORRUPTED(PACK_FILE);
|
|
737
|
+
const access = await fileHandle.createSyncAccessHandle();
|
|
738
|
+
try {
|
|
739
|
+
const size = access.getSize();
|
|
740
|
+
if (size < 8) {
|
|
741
|
+
return {};
|
|
714
742
|
}
|
|
743
|
+
const header = new Uint8Array(8);
|
|
744
|
+
access.read(header, { at: 0 });
|
|
745
|
+
const view = new DataView(header.buffer);
|
|
746
|
+
const indexLen = view.getUint32(0, true);
|
|
747
|
+
const storedCrc = view.getUint32(4, true);
|
|
748
|
+
const contentSize = size - 8;
|
|
749
|
+
const content = new Uint8Array(contentSize);
|
|
750
|
+
access.read(content, { at: 8 });
|
|
751
|
+
if (this.useChecksum && storedCrc !== 0) {
|
|
752
|
+
const calculatedCrc = crc32(content);
|
|
753
|
+
if (calculatedCrc !== storedCrc) {
|
|
754
|
+
throw createECORRUPTED(PACK_FILE);
|
|
755
|
+
}
|
|
756
|
+
}
|
|
757
|
+
const indexJson = new TextDecoder().decode(content.subarray(0, indexLen));
|
|
758
|
+
return JSON.parse(indexJson);
|
|
759
|
+
} finally {
|
|
760
|
+
access.close();
|
|
715
761
|
}
|
|
716
|
-
const indexJson = new TextDecoder().decode(content.subarray(0, indexLen));
|
|
717
|
-
return JSON.parse(indexJson);
|
|
718
762
|
} finally {
|
|
719
|
-
|
|
763
|
+
release();
|
|
720
764
|
}
|
|
721
765
|
} else {
|
|
722
766
|
const file = await fileHandle.getFile();
|
|
@@ -770,12 +814,17 @@ var PackedStorage = class {
|
|
|
770
814
|
if (!fileHandle) return null;
|
|
771
815
|
let buffer;
|
|
772
816
|
if (this.useSync) {
|
|
773
|
-
const
|
|
817
|
+
const release = await fileLock.acquire(PACK_FILE);
|
|
774
818
|
try {
|
|
775
|
-
|
|
776
|
-
|
|
819
|
+
const access = await fileHandle.createSyncAccessHandle();
|
|
820
|
+
try {
|
|
821
|
+
buffer = new Uint8Array(entry.size);
|
|
822
|
+
access.read(buffer, { at: entry.offset });
|
|
823
|
+
} finally {
|
|
824
|
+
access.close();
|
|
825
|
+
}
|
|
777
826
|
} finally {
|
|
778
|
-
|
|
827
|
+
release();
|
|
779
828
|
}
|
|
780
829
|
} else {
|
|
781
830
|
const file = await fileHandle.getFile();
|
|
@@ -815,19 +864,24 @@ var PackedStorage = class {
|
|
|
815
864
|
}
|
|
816
865
|
const decompressPromises = [];
|
|
817
866
|
if (this.useSync) {
|
|
818
|
-
const
|
|
867
|
+
const release = await fileLock.acquire(PACK_FILE);
|
|
819
868
|
try {
|
|
820
|
-
|
|
821
|
-
|
|
822
|
-
|
|
823
|
-
|
|
824
|
-
|
|
825
|
-
|
|
826
|
-
|
|
869
|
+
const access = await fileHandle.createSyncAccessHandle();
|
|
870
|
+
try {
|
|
871
|
+
for (const { path, offset, size, originalSize } of toRead) {
|
|
872
|
+
const buffer = new Uint8Array(size);
|
|
873
|
+
access.read(buffer, { at: offset });
|
|
874
|
+
if (originalSize !== void 0) {
|
|
875
|
+
decompressPromises.push({ path, promise: decompress(buffer) });
|
|
876
|
+
} else {
|
|
877
|
+
results.set(path, buffer);
|
|
878
|
+
}
|
|
827
879
|
}
|
|
880
|
+
} finally {
|
|
881
|
+
access.close();
|
|
828
882
|
}
|
|
829
883
|
} finally {
|
|
830
|
-
|
|
884
|
+
release();
|
|
831
885
|
}
|
|
832
886
|
} else {
|
|
833
887
|
const file = await fileHandle.getFile();
|
|
@@ -915,12 +969,17 @@ var PackedStorage = class {
|
|
|
915
969
|
const { fileHandle } = await this.handleManager.getHandle(PACK_FILE, { create: true });
|
|
916
970
|
if (!fileHandle) return;
|
|
917
971
|
if (this.useSync) {
|
|
918
|
-
const
|
|
972
|
+
const release = await fileLock.acquire(PACK_FILE);
|
|
919
973
|
try {
|
|
920
|
-
access.
|
|
921
|
-
|
|
974
|
+
const access = await fileHandle.createSyncAccessHandle();
|
|
975
|
+
try {
|
|
976
|
+
access.truncate(data.length);
|
|
977
|
+
access.write(data, { at: 0 });
|
|
978
|
+
} finally {
|
|
979
|
+
access.close();
|
|
980
|
+
}
|
|
922
981
|
} finally {
|
|
923
|
-
|
|
982
|
+
release();
|
|
924
983
|
}
|
|
925
984
|
} else {
|
|
926
985
|
const writable = await fileHandle.createWritable();
|
|
@@ -941,35 +1000,40 @@ var PackedStorage = class {
|
|
|
941
1000
|
const encoder = new TextEncoder();
|
|
942
1001
|
const newIndexBuf = encoder.encode(JSON.stringify(index));
|
|
943
1002
|
if (this.useSync) {
|
|
944
|
-
const
|
|
1003
|
+
const release = await fileLock.acquire(PACK_FILE);
|
|
945
1004
|
try {
|
|
946
|
-
const
|
|
947
|
-
|
|
948
|
-
|
|
949
|
-
|
|
950
|
-
|
|
951
|
-
|
|
952
|
-
|
|
953
|
-
|
|
954
|
-
|
|
955
|
-
|
|
956
|
-
|
|
957
|
-
|
|
958
|
-
|
|
959
|
-
newContent.set(
|
|
1005
|
+
const access = await fileHandle.createSyncAccessHandle();
|
|
1006
|
+
try {
|
|
1007
|
+
const size = access.getSize();
|
|
1008
|
+
const oldHeader = new Uint8Array(8);
|
|
1009
|
+
access.read(oldHeader, { at: 0 });
|
|
1010
|
+
const oldIndexLen = new DataView(oldHeader.buffer).getUint32(0, true);
|
|
1011
|
+
const dataStart = 8 + oldIndexLen;
|
|
1012
|
+
const dataSize = size - dataStart;
|
|
1013
|
+
const dataPortion = new Uint8Array(dataSize);
|
|
1014
|
+
if (dataSize > 0) {
|
|
1015
|
+
access.read(dataPortion, { at: dataStart });
|
|
1016
|
+
}
|
|
1017
|
+
const newContent = new Uint8Array(newIndexBuf.length + dataSize);
|
|
1018
|
+
newContent.set(newIndexBuf, 0);
|
|
1019
|
+
if (dataSize > 0) {
|
|
1020
|
+
newContent.set(dataPortion, newIndexBuf.length);
|
|
1021
|
+
}
|
|
1022
|
+
const checksum = this.useChecksum ? crc32(newContent) : 0;
|
|
1023
|
+
const newHeader = new Uint8Array(8);
|
|
1024
|
+
const view = new DataView(newHeader.buffer);
|
|
1025
|
+
view.setUint32(0, newIndexBuf.length, true);
|
|
1026
|
+
view.setUint32(4, checksum, true);
|
|
1027
|
+
const newFile = new Uint8Array(8 + newContent.length);
|
|
1028
|
+
newFile.set(newHeader, 0);
|
|
1029
|
+
newFile.set(newContent, 8);
|
|
1030
|
+
access.truncate(newFile.length);
|
|
1031
|
+
access.write(newFile, { at: 0 });
|
|
1032
|
+
} finally {
|
|
1033
|
+
access.close();
|
|
960
1034
|
}
|
|
961
|
-
const checksum = this.useChecksum ? crc32(newContent) : 0;
|
|
962
|
-
const newHeader = new Uint8Array(8);
|
|
963
|
-
const view = new DataView(newHeader.buffer);
|
|
964
|
-
view.setUint32(0, newIndexBuf.length, true);
|
|
965
|
-
view.setUint32(4, checksum, true);
|
|
966
|
-
const newFile = new Uint8Array(8 + newContent.length);
|
|
967
|
-
newFile.set(newHeader, 0);
|
|
968
|
-
newFile.set(newContent, 8);
|
|
969
|
-
access.truncate(newFile.length);
|
|
970
|
-
access.write(newFile, { at: 0 });
|
|
971
1035
|
} finally {
|
|
972
|
-
|
|
1036
|
+
release();
|
|
973
1037
|
}
|
|
974
1038
|
} else {
|
|
975
1039
|
const file = await fileHandle.getFile();
|