@componentor/fs 1.2.4 → 1.2.5
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 +286 -227
- package/dist/index.js.map +1 -1
- package/dist/opfs-hybrid.js +286 -227
- package/dist/opfs-hybrid.js.map +1 -1
- package/dist/opfs-worker.js +286 -227
- package/dist/opfs-worker.js.map +1 -1
- package/package.json +1 -1
- package/src/handle-manager.ts +64 -0
- package/src/index.ts +51 -19
- package/src/packed-storage.ts +216 -243
- package/src/symlink-manager.ts +15 -6
package/dist/opfs-hybrid.js
CHANGED
|
@@ -145,6 +145,52 @@ 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 FileLockManager = class {
|
|
149
|
+
locks = /* @__PURE__ */ new Map();
|
|
150
|
+
lockResolvers = /* @__PURE__ */ new Map();
|
|
151
|
+
waitQueues = /* @__PURE__ */ new Map();
|
|
152
|
+
/**
|
|
153
|
+
* Acquire an exclusive lock on a file path.
|
|
154
|
+
* If the file is already locked, waits until it's released.
|
|
155
|
+
* Returns a release function that MUST be called when done.
|
|
156
|
+
*/
|
|
157
|
+
async acquire(path) {
|
|
158
|
+
const normalizedPath = normalize(path);
|
|
159
|
+
while (this.locks.has(normalizedPath)) {
|
|
160
|
+
await this.locks.get(normalizedPath);
|
|
161
|
+
}
|
|
162
|
+
let resolve;
|
|
163
|
+
const lockPromise = new Promise((r) => {
|
|
164
|
+
resolve = r;
|
|
165
|
+
});
|
|
166
|
+
this.locks.set(normalizedPath, lockPromise);
|
|
167
|
+
this.lockResolvers.set(normalizedPath, resolve);
|
|
168
|
+
return () => {
|
|
169
|
+
const resolver = this.lockResolvers.get(normalizedPath);
|
|
170
|
+
this.locks.delete(normalizedPath);
|
|
171
|
+
this.lockResolvers.delete(normalizedPath);
|
|
172
|
+
if (resolver) resolver();
|
|
173
|
+
};
|
|
174
|
+
}
|
|
175
|
+
/**
|
|
176
|
+
* Check if a file is currently locked
|
|
177
|
+
*/
|
|
178
|
+
isLocked(path) {
|
|
179
|
+
return this.locks.has(normalize(path));
|
|
180
|
+
}
|
|
181
|
+
/**
|
|
182
|
+
* Clear all locks (use with caution, mainly for cleanup)
|
|
183
|
+
*/
|
|
184
|
+
clearAll() {
|
|
185
|
+
for (const resolver of this.lockResolvers.values()) {
|
|
186
|
+
resolver();
|
|
187
|
+
}
|
|
188
|
+
this.locks.clear();
|
|
189
|
+
this.lockResolvers.clear();
|
|
190
|
+
this.waitQueues.clear();
|
|
191
|
+
}
|
|
192
|
+
};
|
|
193
|
+
var fileLockManager = new FileLockManager();
|
|
148
194
|
var HandleManager = class {
|
|
149
195
|
rootPromise;
|
|
150
196
|
dirCache = /* @__PURE__ */ new Map();
|
|
@@ -402,13 +448,21 @@ var SymlinkManager = class {
|
|
|
402
448
|
if (!fileHandle) return;
|
|
403
449
|
const buffer = new TextEncoder().encode(data);
|
|
404
450
|
if (this.useSync) {
|
|
405
|
-
const
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
451
|
+
const releaseLock = await fileLockManager.acquire(SYMLINK_FILE);
|
|
452
|
+
try {
|
|
453
|
+
const access = await fileHandle.createSyncAccessHandle();
|
|
454
|
+
try {
|
|
455
|
+
access.truncate(0);
|
|
456
|
+
let written = 0;
|
|
457
|
+
while (written < buffer.length) {
|
|
458
|
+
written += access.write(buffer.subarray(written), { at: written });
|
|
459
|
+
}
|
|
460
|
+
} finally {
|
|
461
|
+
access.close();
|
|
462
|
+
}
|
|
463
|
+
} finally {
|
|
464
|
+
releaseLock();
|
|
410
465
|
}
|
|
411
|
-
access.close();
|
|
412
466
|
} else {
|
|
413
467
|
const writable = await fileHandle.createWritable();
|
|
414
468
|
await writable.write(buffer);
|
|
@@ -653,29 +707,12 @@ var PackedStorage = class {
|
|
|
653
707
|
useChecksum;
|
|
654
708
|
index = null;
|
|
655
709
|
indexLoaded = false;
|
|
656
|
-
lockPromise = null;
|
|
657
710
|
constructor(handleManager, useSync, useCompression = false, useChecksum = true) {
|
|
658
711
|
this.handleManager = handleManager;
|
|
659
712
|
this.useSync = useSync;
|
|
660
713
|
this.useCompression = useCompression && typeof CompressionStream !== "undefined";
|
|
661
714
|
this.useChecksum = useChecksum;
|
|
662
715
|
}
|
|
663
|
-
/**
|
|
664
|
-
* Acquire lock for pack file access (prevents concurrent handle conflicts)
|
|
665
|
-
*/
|
|
666
|
-
async acquireLock() {
|
|
667
|
-
while (this.lockPromise) {
|
|
668
|
-
await this.lockPromise;
|
|
669
|
-
}
|
|
670
|
-
let release;
|
|
671
|
-
this.lockPromise = new Promise((resolve) => {
|
|
672
|
-
release = () => {
|
|
673
|
-
this.lockPromise = null;
|
|
674
|
-
resolve();
|
|
675
|
-
};
|
|
676
|
-
});
|
|
677
|
-
return release;
|
|
678
|
-
}
|
|
679
716
|
/**
|
|
680
717
|
* Reset pack storage state (memory only)
|
|
681
718
|
*/
|
|
@@ -707,30 +744,35 @@ var PackedStorage = class {
|
|
|
707
744
|
return {};
|
|
708
745
|
}
|
|
709
746
|
if (this.useSync) {
|
|
710
|
-
const
|
|
747
|
+
const releaseLock = await fileLockManager.acquire(PACK_FILE);
|
|
711
748
|
try {
|
|
712
|
-
const
|
|
713
|
-
|
|
714
|
-
|
|
715
|
-
|
|
716
|
-
|
|
717
|
-
|
|
718
|
-
|
|
719
|
-
|
|
720
|
-
|
|
721
|
-
|
|
722
|
-
|
|
723
|
-
|
|
724
|
-
|
|
725
|
-
|
|
726
|
-
if (
|
|
727
|
-
|
|
749
|
+
const access = await fileHandle.createSyncAccessHandle();
|
|
750
|
+
try {
|
|
751
|
+
const size = access.getSize();
|
|
752
|
+
if (size < 8) {
|
|
753
|
+
return {};
|
|
754
|
+
}
|
|
755
|
+
const header = new Uint8Array(8);
|
|
756
|
+
access.read(header, { at: 0 });
|
|
757
|
+
const view = new DataView(header.buffer);
|
|
758
|
+
const indexLen = view.getUint32(0, true);
|
|
759
|
+
const storedCrc = view.getUint32(4, true);
|
|
760
|
+
const contentSize = size - 8;
|
|
761
|
+
const content = new Uint8Array(contentSize);
|
|
762
|
+
access.read(content, { at: 8 });
|
|
763
|
+
if (this.useChecksum && storedCrc !== 0) {
|
|
764
|
+
const calculatedCrc = crc32(content);
|
|
765
|
+
if (calculatedCrc !== storedCrc) {
|
|
766
|
+
throw createECORRUPTED(PACK_FILE);
|
|
767
|
+
}
|
|
728
768
|
}
|
|
769
|
+
const indexJson = new TextDecoder().decode(content.subarray(0, indexLen));
|
|
770
|
+
return JSON.parse(indexJson);
|
|
771
|
+
} finally {
|
|
772
|
+
access.close();
|
|
729
773
|
}
|
|
730
|
-
const indexJson = new TextDecoder().decode(content.subarray(0, indexLen));
|
|
731
|
-
return JSON.parse(indexJson);
|
|
732
774
|
} finally {
|
|
733
|
-
|
|
775
|
+
releaseLock();
|
|
734
776
|
}
|
|
735
777
|
} else {
|
|
736
778
|
const file = await fileHandle.getFile();
|
|
@@ -759,43 +801,33 @@ var PackedStorage = class {
|
|
|
759
801
|
* Check if a path exists in the pack
|
|
760
802
|
*/
|
|
761
803
|
async has(path) {
|
|
762
|
-
const
|
|
763
|
-
|
|
764
|
-
const index = await this.loadIndex();
|
|
765
|
-
return path in index;
|
|
766
|
-
} finally {
|
|
767
|
-
release();
|
|
768
|
-
}
|
|
804
|
+
const index = await this.loadIndex();
|
|
805
|
+
return path in index;
|
|
769
806
|
}
|
|
770
807
|
/**
|
|
771
808
|
* Get file size from pack (for stat)
|
|
772
809
|
* Returns originalSize if compressed, otherwise size
|
|
773
810
|
*/
|
|
774
811
|
async getSize(path) {
|
|
775
|
-
const
|
|
776
|
-
|
|
777
|
-
|
|
778
|
-
|
|
779
|
-
if (!entry) return null;
|
|
780
|
-
return entry.originalSize ?? entry.size;
|
|
781
|
-
} finally {
|
|
782
|
-
release();
|
|
783
|
-
}
|
|
812
|
+
const index = await this.loadIndex();
|
|
813
|
+
const entry = index[path];
|
|
814
|
+
if (!entry) return null;
|
|
815
|
+
return entry.originalSize ?? entry.size;
|
|
784
816
|
}
|
|
785
817
|
/**
|
|
786
818
|
* Read a file from the pack
|
|
787
819
|
* Handles decompression if file was stored compressed
|
|
788
820
|
*/
|
|
789
821
|
async read(path) {
|
|
790
|
-
const
|
|
791
|
-
|
|
792
|
-
|
|
793
|
-
|
|
794
|
-
|
|
795
|
-
|
|
796
|
-
|
|
797
|
-
|
|
798
|
-
|
|
822
|
+
const index = await this.loadIndex();
|
|
823
|
+
const entry = index[path];
|
|
824
|
+
if (!entry) return null;
|
|
825
|
+
const { fileHandle } = await this.handleManager.getHandle(PACK_FILE);
|
|
826
|
+
if (!fileHandle) return null;
|
|
827
|
+
let buffer;
|
|
828
|
+
if (this.useSync) {
|
|
829
|
+
const releaseLock = await fileLockManager.acquire(PACK_FILE);
|
|
830
|
+
try {
|
|
799
831
|
const access = await fileHandle.createSyncAccessHandle();
|
|
800
832
|
try {
|
|
801
833
|
buffer = new Uint8Array(entry.size);
|
|
@@ -803,18 +835,18 @@ var PackedStorage = class {
|
|
|
803
835
|
} finally {
|
|
804
836
|
access.close();
|
|
805
837
|
}
|
|
806
|
-
}
|
|
807
|
-
|
|
808
|
-
const data = new Uint8Array(await file.arrayBuffer());
|
|
809
|
-
buffer = data.slice(entry.offset, entry.offset + entry.size);
|
|
810
|
-
}
|
|
811
|
-
if (entry.originalSize !== void 0) {
|
|
812
|
-
return decompress(buffer);
|
|
838
|
+
} finally {
|
|
839
|
+
releaseLock();
|
|
813
840
|
}
|
|
814
|
-
|
|
815
|
-
|
|
816
|
-
|
|
841
|
+
} else {
|
|
842
|
+
const file = await fileHandle.getFile();
|
|
843
|
+
const data = new Uint8Array(await file.arrayBuffer());
|
|
844
|
+
buffer = data.slice(entry.offset, entry.offset + entry.size);
|
|
845
|
+
}
|
|
846
|
+
if (entry.originalSize !== void 0) {
|
|
847
|
+
return decompress(buffer);
|
|
817
848
|
}
|
|
849
|
+
return buffer;
|
|
818
850
|
}
|
|
819
851
|
/**
|
|
820
852
|
* Read multiple files from the pack in a single operation
|
|
@@ -824,28 +856,28 @@ var PackedStorage = class {
|
|
|
824
856
|
async readBatch(paths) {
|
|
825
857
|
const results = /* @__PURE__ */ new Map();
|
|
826
858
|
if (paths.length === 0) return results;
|
|
827
|
-
const
|
|
828
|
-
|
|
829
|
-
|
|
830
|
-
const
|
|
831
|
-
|
|
832
|
-
|
|
833
|
-
|
|
834
|
-
|
|
835
|
-
} else {
|
|
836
|
-
results.set(path, null);
|
|
837
|
-
}
|
|
859
|
+
const index = await this.loadIndex();
|
|
860
|
+
const toRead = [];
|
|
861
|
+
for (const path of paths) {
|
|
862
|
+
const entry = index[path];
|
|
863
|
+
if (entry) {
|
|
864
|
+
toRead.push({ path, offset: entry.offset, size: entry.size, originalSize: entry.originalSize });
|
|
865
|
+
} else {
|
|
866
|
+
results.set(path, null);
|
|
838
867
|
}
|
|
839
|
-
|
|
840
|
-
|
|
841
|
-
|
|
842
|
-
|
|
843
|
-
|
|
844
|
-
|
|
845
|
-
return results;
|
|
868
|
+
}
|
|
869
|
+
if (toRead.length === 0) return results;
|
|
870
|
+
const { fileHandle } = await this.handleManager.getHandle(PACK_FILE);
|
|
871
|
+
if (!fileHandle) {
|
|
872
|
+
for (const { path } of toRead) {
|
|
873
|
+
results.set(path, null);
|
|
846
874
|
}
|
|
847
|
-
|
|
848
|
-
|
|
875
|
+
return results;
|
|
876
|
+
}
|
|
877
|
+
const decompressPromises = [];
|
|
878
|
+
if (this.useSync) {
|
|
879
|
+
const releaseLock = await fileLockManager.acquire(PACK_FILE);
|
|
880
|
+
try {
|
|
849
881
|
const access = await fileHandle.createSyncAccessHandle();
|
|
850
882
|
try {
|
|
851
883
|
for (const { path, offset, size, originalSize } of toRead) {
|
|
@@ -860,25 +892,25 @@ var PackedStorage = class {
|
|
|
860
892
|
} finally {
|
|
861
893
|
access.close();
|
|
862
894
|
}
|
|
863
|
-
}
|
|
864
|
-
|
|
865
|
-
const data = new Uint8Array(await file.arrayBuffer());
|
|
866
|
-
for (const { path, offset, size, originalSize } of toRead) {
|
|
867
|
-
const buffer = data.slice(offset, offset + size);
|
|
868
|
-
if (originalSize !== void 0) {
|
|
869
|
-
decompressPromises.push({ path, promise: decompress(buffer) });
|
|
870
|
-
} else {
|
|
871
|
-
results.set(path, buffer);
|
|
872
|
-
}
|
|
873
|
-
}
|
|
895
|
+
} finally {
|
|
896
|
+
releaseLock();
|
|
874
897
|
}
|
|
875
|
-
|
|
876
|
-
|
|
898
|
+
} else {
|
|
899
|
+
const file = await fileHandle.getFile();
|
|
900
|
+
const data = new Uint8Array(await file.arrayBuffer());
|
|
901
|
+
for (const { path, offset, size, originalSize } of toRead) {
|
|
902
|
+
const buffer = data.slice(offset, offset + size);
|
|
903
|
+
if (originalSize !== void 0) {
|
|
904
|
+
decompressPromises.push({ path, promise: decompress(buffer) });
|
|
905
|
+
} else {
|
|
906
|
+
results.set(path, buffer);
|
|
907
|
+
}
|
|
877
908
|
}
|
|
878
|
-
return results;
|
|
879
|
-
} finally {
|
|
880
|
-
release();
|
|
881
909
|
}
|
|
910
|
+
for (const { path, promise } of decompressPromises) {
|
|
911
|
+
results.set(path, await promise);
|
|
912
|
+
}
|
|
913
|
+
return results;
|
|
882
914
|
}
|
|
883
915
|
/**
|
|
884
916
|
* Write multiple files to the pack in a single operation
|
|
@@ -889,62 +921,57 @@ var PackedStorage = class {
|
|
|
889
921
|
*/
|
|
890
922
|
async writeBatch(entries) {
|
|
891
923
|
if (entries.length === 0) return;
|
|
892
|
-
const
|
|
893
|
-
|
|
894
|
-
|
|
895
|
-
|
|
896
|
-
|
|
897
|
-
|
|
898
|
-
|
|
899
|
-
|
|
900
|
-
if (compressed.length < data.length) {
|
|
901
|
-
return { path, data: compressed, originalSize: data.length };
|
|
902
|
-
}
|
|
903
|
-
return { path, data };
|
|
904
|
-
})
|
|
905
|
-
);
|
|
906
|
-
} else {
|
|
907
|
-
processedEntries = entries;
|
|
908
|
-
}
|
|
909
|
-
let totalDataSize = 0;
|
|
910
|
-
for (const { data } of processedEntries) {
|
|
911
|
-
totalDataSize += data.length;
|
|
912
|
-
}
|
|
913
|
-
const newIndex = {};
|
|
914
|
-
let headerSize = 8;
|
|
915
|
-
let prevHeaderSize = 0;
|
|
916
|
-
while (headerSize !== prevHeaderSize) {
|
|
917
|
-
prevHeaderSize = headerSize;
|
|
918
|
-
let currentOffset = headerSize;
|
|
919
|
-
for (const { path, data, originalSize } of processedEntries) {
|
|
920
|
-
const entry = { offset: currentOffset, size: data.length };
|
|
921
|
-
if (originalSize !== void 0) {
|
|
922
|
-
entry.originalSize = originalSize;
|
|
924
|
+
const encoder = new TextEncoder();
|
|
925
|
+
let processedEntries;
|
|
926
|
+
if (this.useCompression) {
|
|
927
|
+
processedEntries = await Promise.all(
|
|
928
|
+
entries.map(async ({ path, data }) => {
|
|
929
|
+
const compressed = await compress(data);
|
|
930
|
+
if (compressed.length < data.length) {
|
|
931
|
+
return { path, data: compressed, originalSize: data.length };
|
|
923
932
|
}
|
|
924
|
-
|
|
925
|
-
|
|
933
|
+
return { path, data };
|
|
934
|
+
})
|
|
935
|
+
);
|
|
936
|
+
} else {
|
|
937
|
+
processedEntries = entries;
|
|
938
|
+
}
|
|
939
|
+
let totalDataSize = 0;
|
|
940
|
+
for (const { data } of processedEntries) {
|
|
941
|
+
totalDataSize += data.length;
|
|
942
|
+
}
|
|
943
|
+
const newIndex = {};
|
|
944
|
+
let headerSize = 8;
|
|
945
|
+
let prevHeaderSize = 0;
|
|
946
|
+
while (headerSize !== prevHeaderSize) {
|
|
947
|
+
prevHeaderSize = headerSize;
|
|
948
|
+
let currentOffset = headerSize;
|
|
949
|
+
for (const { path, data, originalSize } of processedEntries) {
|
|
950
|
+
const entry = { offset: currentOffset, size: data.length };
|
|
951
|
+
if (originalSize !== void 0) {
|
|
952
|
+
entry.originalSize = originalSize;
|
|
926
953
|
}
|
|
927
|
-
|
|
928
|
-
|
|
929
|
-
}
|
|
930
|
-
const
|
|
931
|
-
|
|
932
|
-
const packBuffer = new Uint8Array(totalSize);
|
|
933
|
-
const view = new DataView(packBuffer.buffer);
|
|
934
|
-
packBuffer.set(finalIndexBuf, 8);
|
|
935
|
-
for (const { path, data } of processedEntries) {
|
|
936
|
-
const entry = newIndex[path];
|
|
937
|
-
packBuffer.set(data, entry.offset);
|
|
938
|
-
}
|
|
939
|
-
const content = packBuffer.subarray(8);
|
|
940
|
-
const checksum = this.useChecksum ? crc32(content) : 0;
|
|
941
|
-
view.setUint32(0, finalIndexBuf.length, true);
|
|
942
|
-
view.setUint32(4, checksum, true);
|
|
943
|
-
await this.writePackFile(packBuffer);
|
|
944
|
-
this.index = newIndex;
|
|
945
|
-
} finally {
|
|
946
|
-
release();
|
|
954
|
+
newIndex[path] = entry;
|
|
955
|
+
currentOffset += data.length;
|
|
956
|
+
}
|
|
957
|
+
const indexBuf = encoder.encode(JSON.stringify(newIndex));
|
|
958
|
+
headerSize = 8 + indexBuf.length;
|
|
947
959
|
}
|
|
960
|
+
const finalIndexBuf = encoder.encode(JSON.stringify(newIndex));
|
|
961
|
+
const totalSize = headerSize + totalDataSize;
|
|
962
|
+
const packBuffer = new Uint8Array(totalSize);
|
|
963
|
+
const view = new DataView(packBuffer.buffer);
|
|
964
|
+
packBuffer.set(finalIndexBuf, 8);
|
|
965
|
+
for (const { path, data } of processedEntries) {
|
|
966
|
+
const entry = newIndex[path];
|
|
967
|
+
packBuffer.set(data, entry.offset);
|
|
968
|
+
}
|
|
969
|
+
const content = packBuffer.subarray(8);
|
|
970
|
+
const checksum = this.useChecksum ? crc32(content) : 0;
|
|
971
|
+
view.setUint32(0, finalIndexBuf.length, true);
|
|
972
|
+
view.setUint32(4, checksum, true);
|
|
973
|
+
await this.writePackFile(packBuffer);
|
|
974
|
+
this.index = newIndex;
|
|
948
975
|
}
|
|
949
976
|
/**
|
|
950
977
|
* Write the pack file to OPFS
|
|
@@ -954,12 +981,17 @@ var PackedStorage = class {
|
|
|
954
981
|
const { fileHandle } = await this.handleManager.getHandle(PACK_FILE, { create: true });
|
|
955
982
|
if (!fileHandle) return;
|
|
956
983
|
if (this.useSync) {
|
|
957
|
-
const
|
|
984
|
+
const releaseLock = await fileLockManager.acquire(PACK_FILE);
|
|
958
985
|
try {
|
|
959
|
-
access.
|
|
960
|
-
|
|
986
|
+
const access = await fileHandle.createSyncAccessHandle();
|
|
987
|
+
try {
|
|
988
|
+
access.truncate(data.length);
|
|
989
|
+
access.write(data, { at: 0 });
|
|
990
|
+
} finally {
|
|
991
|
+
access.close();
|
|
992
|
+
}
|
|
961
993
|
} finally {
|
|
962
|
-
|
|
994
|
+
releaseLock();
|
|
963
995
|
}
|
|
964
996
|
} else {
|
|
965
997
|
const writable = await fileHandle.createWritable();
|
|
@@ -972,16 +1004,16 @@ var PackedStorage = class {
|
|
|
972
1004
|
* Note: Doesn't reclaim space, just removes from index and recalculates CRC32
|
|
973
1005
|
*/
|
|
974
1006
|
async remove(path) {
|
|
975
|
-
const
|
|
976
|
-
|
|
977
|
-
|
|
978
|
-
|
|
979
|
-
|
|
980
|
-
|
|
981
|
-
|
|
982
|
-
|
|
983
|
-
const
|
|
984
|
-
|
|
1007
|
+
const index = await this.loadIndex();
|
|
1008
|
+
if (!(path in index)) return false;
|
|
1009
|
+
delete index[path];
|
|
1010
|
+
const { fileHandle } = await this.handleManager.getHandle(PACK_FILE);
|
|
1011
|
+
if (!fileHandle) return true;
|
|
1012
|
+
const encoder = new TextEncoder();
|
|
1013
|
+
const newIndexBuf = encoder.encode(JSON.stringify(index));
|
|
1014
|
+
if (this.useSync) {
|
|
1015
|
+
const releaseLock = await fileLockManager.acquire(PACK_FILE);
|
|
1016
|
+
try {
|
|
985
1017
|
const access = await fileHandle.createSyncAccessHandle();
|
|
986
1018
|
try {
|
|
987
1019
|
const size = access.getSize();
|
|
@@ -1012,42 +1044,37 @@ var PackedStorage = class {
|
|
|
1012
1044
|
} finally {
|
|
1013
1045
|
access.close();
|
|
1014
1046
|
}
|
|
1015
|
-
}
|
|
1016
|
-
|
|
1017
|
-
const oldData = new Uint8Array(await file.arrayBuffer());
|
|
1018
|
-
if (oldData.length < 8) return true;
|
|
1019
|
-
const oldIndexLen = new DataView(oldData.buffer).getUint32(0, true);
|
|
1020
|
-
const dataStart = 8 + oldIndexLen;
|
|
1021
|
-
const dataPortion = oldData.subarray(dataStart);
|
|
1022
|
-
const newContent = new Uint8Array(newIndexBuf.length + dataPortion.length);
|
|
1023
|
-
newContent.set(newIndexBuf, 0);
|
|
1024
|
-
newContent.set(dataPortion, newIndexBuf.length);
|
|
1025
|
-
const checksum = this.useChecksum ? crc32(newContent) : 0;
|
|
1026
|
-
const newFile = new Uint8Array(8 + newContent.length);
|
|
1027
|
-
const view = new DataView(newFile.buffer);
|
|
1028
|
-
view.setUint32(0, newIndexBuf.length, true);
|
|
1029
|
-
view.setUint32(4, checksum, true);
|
|
1030
|
-
newFile.set(newContent, 8);
|
|
1031
|
-
const writable = await fileHandle.createWritable();
|
|
1032
|
-
await writable.write(newFile);
|
|
1033
|
-
await writable.close();
|
|
1047
|
+
} finally {
|
|
1048
|
+
releaseLock();
|
|
1034
1049
|
}
|
|
1035
|
-
|
|
1036
|
-
|
|
1037
|
-
|
|
1050
|
+
} else {
|
|
1051
|
+
const file = await fileHandle.getFile();
|
|
1052
|
+
const oldData = new Uint8Array(await file.arrayBuffer());
|
|
1053
|
+
if (oldData.length < 8) return true;
|
|
1054
|
+
const oldIndexLen = new DataView(oldData.buffer).getUint32(0, true);
|
|
1055
|
+
const dataStart = 8 + oldIndexLen;
|
|
1056
|
+
const dataPortion = oldData.subarray(dataStart);
|
|
1057
|
+
const newContent = new Uint8Array(newIndexBuf.length + dataPortion.length);
|
|
1058
|
+
newContent.set(newIndexBuf, 0);
|
|
1059
|
+
newContent.set(dataPortion, newIndexBuf.length);
|
|
1060
|
+
const checksum = this.useChecksum ? crc32(newContent) : 0;
|
|
1061
|
+
const newFile = new Uint8Array(8 + newContent.length);
|
|
1062
|
+
const view = new DataView(newFile.buffer);
|
|
1063
|
+
view.setUint32(0, newIndexBuf.length, true);
|
|
1064
|
+
view.setUint32(4, checksum, true);
|
|
1065
|
+
newFile.set(newContent, 8);
|
|
1066
|
+
const writable = await fileHandle.createWritable();
|
|
1067
|
+
await writable.write(newFile);
|
|
1068
|
+
await writable.close();
|
|
1038
1069
|
}
|
|
1070
|
+
return true;
|
|
1039
1071
|
}
|
|
1040
1072
|
/**
|
|
1041
1073
|
* Check if pack file is being used (has entries)
|
|
1042
1074
|
*/
|
|
1043
1075
|
async isEmpty() {
|
|
1044
|
-
const
|
|
1045
|
-
|
|
1046
|
-
const index = await this.loadIndex();
|
|
1047
|
-
return Object.keys(index).length === 0;
|
|
1048
|
-
} finally {
|
|
1049
|
-
release();
|
|
1050
|
-
}
|
|
1076
|
+
const index = await this.loadIndex();
|
|
1077
|
+
return Object.keys(index).length === 0;
|
|
1051
1078
|
}
|
|
1052
1079
|
};
|
|
1053
1080
|
|
|
@@ -1283,11 +1310,19 @@ var OPFS = class {
|
|
|
1283
1310
|
if (fileHandle) {
|
|
1284
1311
|
let buffer;
|
|
1285
1312
|
if (this.useSync) {
|
|
1286
|
-
const
|
|
1287
|
-
|
|
1288
|
-
|
|
1289
|
-
|
|
1290
|
-
|
|
1313
|
+
const releaseLock = await fileLockManager.acquire(resolvedPath);
|
|
1314
|
+
try {
|
|
1315
|
+
const access = await fileHandle.createSyncAccessHandle();
|
|
1316
|
+
try {
|
|
1317
|
+
const size = access.getSize();
|
|
1318
|
+
buffer = new Uint8Array(size);
|
|
1319
|
+
access.read(buffer);
|
|
1320
|
+
} finally {
|
|
1321
|
+
access.close();
|
|
1322
|
+
}
|
|
1323
|
+
} finally {
|
|
1324
|
+
releaseLock();
|
|
1325
|
+
}
|
|
1291
1326
|
} else {
|
|
1292
1327
|
const file = await fileHandle.getFile();
|
|
1293
1328
|
buffer = new Uint8Array(await file.arrayBuffer());
|
|
@@ -1344,11 +1379,19 @@ var OPFS = class {
|
|
|
1344
1379
|
}
|
|
1345
1380
|
let buffer;
|
|
1346
1381
|
if (this.useSync) {
|
|
1347
|
-
const
|
|
1348
|
-
|
|
1349
|
-
|
|
1350
|
-
|
|
1351
|
-
|
|
1382
|
+
const releaseLock = await fileLockManager.acquire(resolvedPath);
|
|
1383
|
+
try {
|
|
1384
|
+
const access = await fileHandle.createSyncAccessHandle();
|
|
1385
|
+
try {
|
|
1386
|
+
const size = access.getSize();
|
|
1387
|
+
buffer = new Uint8Array(size);
|
|
1388
|
+
access.read(buffer);
|
|
1389
|
+
} finally {
|
|
1390
|
+
access.close();
|
|
1391
|
+
}
|
|
1392
|
+
} finally {
|
|
1393
|
+
releaseLock();
|
|
1394
|
+
}
|
|
1352
1395
|
} else {
|
|
1353
1396
|
const file = await fileHandle.getFile();
|
|
1354
1397
|
buffer = new Uint8Array(await file.arrayBuffer());
|
|
@@ -1380,10 +1423,18 @@ var OPFS = class {
|
|
|
1380
1423
|
const { fileHandle } = await this.handleManager.getHandle(resolvedPath, { create: true });
|
|
1381
1424
|
const buffer = typeof data === "string" ? new TextEncoder().encode(data) : data;
|
|
1382
1425
|
if (this.useSync) {
|
|
1383
|
-
const
|
|
1384
|
-
|
|
1385
|
-
|
|
1386
|
-
|
|
1426
|
+
const releaseLock = await fileLockManager.acquire(resolvedPath);
|
|
1427
|
+
try {
|
|
1428
|
+
const access = await fileHandle.createSyncAccessHandle();
|
|
1429
|
+
try {
|
|
1430
|
+
access.truncate(buffer.length);
|
|
1431
|
+
access.write(buffer, { at: 0 });
|
|
1432
|
+
} finally {
|
|
1433
|
+
access.close();
|
|
1434
|
+
}
|
|
1435
|
+
} finally {
|
|
1436
|
+
releaseLock();
|
|
1437
|
+
}
|
|
1387
1438
|
} else {
|
|
1388
1439
|
const writable = await fileHandle.createWritable();
|
|
1389
1440
|
await writable.write(buffer);
|
|
@@ -1996,9 +2047,17 @@ var OPFS = class {
|
|
|
1996
2047
|
const { fileHandle } = await this.handleManager.getHandle(resolvedPath);
|
|
1997
2048
|
if (!fileHandle) throw createENOENT(path);
|
|
1998
2049
|
if (this.useSync) {
|
|
1999
|
-
const
|
|
2000
|
-
|
|
2001
|
-
|
|
2050
|
+
const releaseLock = await fileLockManager.acquire(resolvedPath);
|
|
2051
|
+
try {
|
|
2052
|
+
const access = await fileHandle.createSyncAccessHandle();
|
|
2053
|
+
try {
|
|
2054
|
+
access.truncate(len);
|
|
2055
|
+
} finally {
|
|
2056
|
+
access.close();
|
|
2057
|
+
}
|
|
2058
|
+
} finally {
|
|
2059
|
+
releaseLock();
|
|
2060
|
+
}
|
|
2002
2061
|
} else {
|
|
2003
2062
|
const file = await fileHandle.getFile();
|
|
2004
2063
|
const data = new Uint8Array(await file.arrayBuffer());
|