@volter/tabnode 0.5.45 → 0.5.46
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.
|
@@ -8686,6 +8686,26 @@ function createFsBindings(Bytes = () => Buffer$9) {
|
|
|
8686
8686
|
if (position === null || position === void 0 || position < 0) file.position = end + slice.length;
|
|
8687
8687
|
return slice.length;
|
|
8688
8688
|
}
|
|
8689
|
+
if (typeof tree2.writeAtSync === "function") {
|
|
8690
|
+
const at22 = position === null || position === void 0 || position < 0 ? file.position : position;
|
|
8691
|
+
tree2.writeAtSync(file.path, slice, at22);
|
|
8692
|
+
if (file.cached !== void 0 && slice.length > 0) {
|
|
8693
|
+
const cached = file.cached;
|
|
8694
|
+
const length2 = Math.max(cached.length, at22 + slice.length);
|
|
8695
|
+
let room = file.room;
|
|
8696
|
+
if (!room || cached.buffer !== room.buffer || cached.byteOffset !== 0 || room.byteLength < length2) {
|
|
8697
|
+
room = new Uint8Array(Math.max(length2, cached.length * 2, 4096));
|
|
8698
|
+
room.set(cached, 0);
|
|
8699
|
+
} else if (at22 > cached.length) {
|
|
8700
|
+
room.fill(0, cached.length, at22);
|
|
8701
|
+
}
|
|
8702
|
+
room.set(slice, at22);
|
|
8703
|
+
file.cached = room.subarray(0, length2);
|
|
8704
|
+
file.room = room;
|
|
8705
|
+
}
|
|
8706
|
+
if (position === null || position === void 0 || position < 0) file.position = at22 + slice.length;
|
|
8707
|
+
return slice.length;
|
|
8708
|
+
}
|
|
8689
8709
|
const existing = file.cached ?? (tree2.existsSync(file.path) ? tree2.readFileSync(file.path) : new Uint8Array(0));
|
|
8690
8710
|
const at3 = (file.flags & flagBits().append) !== 0 ? existing.length : position === null || position === void 0 || position < 0 ? file.position : position;
|
|
8691
8711
|
const size = Math.max(existing.length, at3 + slice.length);
|
|
@@ -31445,6 +31465,8 @@ class VirtualFS {
|
|
|
31445
31465
|
if (existed && existing.type === "file") {
|
|
31446
31466
|
existing.content = content;
|
|
31447
31467
|
existing.mtime = Date.now();
|
|
31468
|
+
existing.room = void 0;
|
|
31469
|
+
existing.lent = true;
|
|
31448
31470
|
} else {
|
|
31449
31471
|
parent.children.set(basename, {
|
|
31450
31472
|
type: "file",
|
|
@@ -31730,6 +31752,7 @@ class VirtualFS {
|
|
|
31730
31752
|
if (encoding === "utf8" || encoding === "utf-8") {
|
|
31731
31753
|
return this.decoder.decode(content);
|
|
31732
31754
|
}
|
|
31755
|
+
node.lent = true;
|
|
31733
31756
|
return content;
|
|
31734
31757
|
}
|
|
31735
31758
|
/**
|
|
@@ -31779,6 +31802,55 @@ class VirtualFS {
|
|
|
31779
31802
|
this.notifyWatchers(normalized, "change");
|
|
31780
31803
|
if ((_a3 = this.eventListeners.get("change")) == null ? void 0 : _a3.size) this.emit("change", normalized, this.decoder.decode(node.content));
|
|
31781
31804
|
}
|
|
31805
|
+
/**
|
|
31806
|
+
* Bytes written into a file at `position`, as a disk takes them: a gap past
|
|
31807
|
+
* the end reads as zeros, and the file grows in its own buffer as an append
|
|
31808
|
+
* grows it. A database rewrites its log and its pages a page at a time;
|
|
31809
|
+
* writing the whole file again for each page copied Postgres's 16 MB
|
|
31810
|
+
* write-ahead log at every commit. A tree that keeps its files elsewhere
|
|
31811
|
+
* (its own writeFileSync) is written through its own read and write unless
|
|
31812
|
+
* it answers this itself.
|
|
31813
|
+
*/
|
|
31814
|
+
writeAtSync(path2, data2, position) {
|
|
31815
|
+
var _a3;
|
|
31816
|
+
if (this.writeFileSync !== VirtualFS.prototype.writeFileSync) {
|
|
31817
|
+
const existing = this.existsSync(path2) ? this.readFileSync(path2) : new Uint8Array(0);
|
|
31818
|
+
if (data2.byteLength === 0 && this.existsSync(path2)) return;
|
|
31819
|
+
const whole = new Uint8Array(Math.max(existing.byteLength, position + data2.byteLength));
|
|
31820
|
+
whole.set(existing, 0);
|
|
31821
|
+
whole.set(data2, position);
|
|
31822
|
+
this.writeFileSync(path2, whole);
|
|
31823
|
+
return;
|
|
31824
|
+
}
|
|
31825
|
+
const normalized = this.normalizePath(path2);
|
|
31826
|
+
const node = this.getNode(normalized);
|
|
31827
|
+
if (!node) {
|
|
31828
|
+
const whole = new Uint8Array(position + data2.byteLength);
|
|
31829
|
+
whole.set(data2, position);
|
|
31830
|
+
this.writeFileSyncInternal(normalized, whole, true);
|
|
31831
|
+
return;
|
|
31832
|
+
}
|
|
31833
|
+
if (node.type !== "file") throw createNodeError("EISDIR", "open", path2);
|
|
31834
|
+
this.assertWritable(normalized, "open");
|
|
31835
|
+
if (data2.byteLength === 0) return;
|
|
31836
|
+
const current3 = node.content ?? new Uint8Array(0);
|
|
31837
|
+
const length = Math.max(current3.byteLength, position + data2.byteLength);
|
|
31838
|
+
const held = node;
|
|
31839
|
+
let room = held.room;
|
|
31840
|
+
if (!room || held.lent || current3.buffer !== room.buffer || current3.byteOffset !== 0 || room.byteLength < length) {
|
|
31841
|
+
room = new Uint8Array(Math.max(length, current3.byteLength * 2, 4096));
|
|
31842
|
+
room.set(current3, 0);
|
|
31843
|
+
held.lent = false;
|
|
31844
|
+
} else if (position > current3.byteLength) {
|
|
31845
|
+
room.fill(0, current3.byteLength, position);
|
|
31846
|
+
}
|
|
31847
|
+
room.set(data2, position);
|
|
31848
|
+
node.content = room.subarray(0, length);
|
|
31849
|
+
node.room = room;
|
|
31850
|
+
node.mtime = Date.now();
|
|
31851
|
+
this.notifyWatchers(normalized, "change");
|
|
31852
|
+
if ((_a3 = this.eventListeners.get("change")) == null ? void 0 : _a3.size) this.emit("change", normalized, this.decoder.decode(node.content));
|
|
31853
|
+
}
|
|
31782
31854
|
/**
|
|
31783
31855
|
* Create directory, optionally with recursive parent creation
|
|
31784
31856
|
*/
|
|
@@ -79994,10 +80066,28 @@ function createRequire(vfs2, fsShim, process2, currentDir, moduleCache, options,
|
|
|
79994
80066
|
}
|
|
79995
80067
|
return loadModule(resolved).exports;
|
|
79996
80068
|
};
|
|
79997
|
-
require2.resolve = (id2) => {
|
|
80069
|
+
require2.resolve = (id2, options2) => {
|
|
79998
80070
|
if (id2 === "fs" || id2 === "process" || id2.startsWith("node:") || builtinModules$1.includes(id2)) {
|
|
79999
80071
|
return id2;
|
|
80000
80072
|
}
|
|
80073
|
+
if (options2 && options2.paths !== void 0) {
|
|
80074
|
+
if (!Array.isArray(options2.paths)) {
|
|
80075
|
+
throw Object.assign(new TypeError(`The property 'options.paths' must be an Array. Received ${String(options2.paths)}`), { code: "ERR_INVALID_ARG_VALUE" });
|
|
80076
|
+
}
|
|
80077
|
+
options2.paths.forEach((from, index2) => {
|
|
80078
|
+
if (typeof from !== "string") throw Object.assign(new TypeError(`The "paths[${index2}]" argument must be of type string. Received ${typeof from}`), { code: "ERR_INVALID_ARG_TYPE" });
|
|
80079
|
+
});
|
|
80080
|
+
const requireStack = parentModule && typeof parentModule.filename === "string" ? [parentModule.filename] : [];
|
|
80081
|
+
for (const from of options2.paths) {
|
|
80082
|
+
try {
|
|
80083
|
+
return resolveModule(id2, resolve(process2.cwd(), from));
|
|
80084
|
+
} catch {
|
|
80085
|
+
}
|
|
80086
|
+
}
|
|
80087
|
+
throw Object.assign(new Error(`Cannot find module '${id2}'${requireStack.length ? `
|
|
80088
|
+
Require stack:
|
|
80089
|
+
- ${requireStack.join("\n- ")}` : ""}`), { code: "MODULE_NOT_FOUND", requireStack });
|
|
80090
|
+
}
|
|
80001
80091
|
return resolveModule(id2, currentDir);
|
|
80002
80092
|
};
|
|
80003
80093
|
require2.cache = moduleCache;
|
package/dist/index.mjs
CHANGED
|
@@ -8814,6 +8814,26 @@ function createFsBindings(Bytes = () => Buffer$9) {
|
|
|
8814
8814
|
if (position === null || position === void 0 || position < 0) file.position = end + slice.length;
|
|
8815
8815
|
return slice.length;
|
|
8816
8816
|
}
|
|
8817
|
+
if (typeof tree2.writeAtSync === "function") {
|
|
8818
|
+
const at22 = position === null || position === void 0 || position < 0 ? file.position : position;
|
|
8819
|
+
tree2.writeAtSync(file.path, slice, at22);
|
|
8820
|
+
if (file.cached !== void 0 && slice.length > 0) {
|
|
8821
|
+
const cached = file.cached;
|
|
8822
|
+
const length2 = Math.max(cached.length, at22 + slice.length);
|
|
8823
|
+
let room = file.room;
|
|
8824
|
+
if (!room || cached.buffer !== room.buffer || cached.byteOffset !== 0 || room.byteLength < length2) {
|
|
8825
|
+
room = new Uint8Array(Math.max(length2, cached.length * 2, 4096));
|
|
8826
|
+
room.set(cached, 0);
|
|
8827
|
+
} else if (at22 > cached.length) {
|
|
8828
|
+
room.fill(0, cached.length, at22);
|
|
8829
|
+
}
|
|
8830
|
+
room.set(slice, at22);
|
|
8831
|
+
file.cached = room.subarray(0, length2);
|
|
8832
|
+
file.room = room;
|
|
8833
|
+
}
|
|
8834
|
+
if (position === null || position === void 0 || position < 0) file.position = at22 + slice.length;
|
|
8835
|
+
return slice.length;
|
|
8836
|
+
}
|
|
8817
8837
|
const existing = file.cached ?? (tree2.existsSync(file.path) ? tree2.readFileSync(file.path) : new Uint8Array(0));
|
|
8818
8838
|
const at2 = (file.flags & flagBits().append) !== 0 ? existing.length : position === null || position === void 0 || position < 0 ? file.position : position;
|
|
8819
8839
|
const size = Math.max(existing.length, at2 + slice.length);
|
|
@@ -31599,6 +31619,8 @@ class VirtualFS {
|
|
|
31599
31619
|
if (existed && existing.type === "file") {
|
|
31600
31620
|
existing.content = content;
|
|
31601
31621
|
existing.mtime = Date.now();
|
|
31622
|
+
existing.room = void 0;
|
|
31623
|
+
existing.lent = true;
|
|
31602
31624
|
} else {
|
|
31603
31625
|
parent.children.set(basename2, {
|
|
31604
31626
|
type: "file",
|
|
@@ -31884,6 +31906,7 @@ class VirtualFS {
|
|
|
31884
31906
|
if (encoding === "utf8" || encoding === "utf-8") {
|
|
31885
31907
|
return this.decoder.decode(content);
|
|
31886
31908
|
}
|
|
31909
|
+
node.lent = true;
|
|
31887
31910
|
return content;
|
|
31888
31911
|
}
|
|
31889
31912
|
/**
|
|
@@ -31933,6 +31956,55 @@ class VirtualFS {
|
|
|
31933
31956
|
this.notifyWatchers(normalized, "change");
|
|
31934
31957
|
if ((_a2 = this.eventListeners.get("change")) == null ? void 0 : _a2.size) this.emit("change", normalized, this.decoder.decode(node.content));
|
|
31935
31958
|
}
|
|
31959
|
+
/**
|
|
31960
|
+
* Bytes written into a file at `position`, as a disk takes them: a gap past
|
|
31961
|
+
* the end reads as zeros, and the file grows in its own buffer as an append
|
|
31962
|
+
* grows it. A database rewrites its log and its pages a page at a time;
|
|
31963
|
+
* writing the whole file again for each page copied Postgres's 16 MB
|
|
31964
|
+
* write-ahead log at every commit. A tree that keeps its files elsewhere
|
|
31965
|
+
* (its own writeFileSync) is written through its own read and write unless
|
|
31966
|
+
* it answers this itself.
|
|
31967
|
+
*/
|
|
31968
|
+
writeAtSync(path2, data2, position) {
|
|
31969
|
+
var _a2;
|
|
31970
|
+
if (this.writeFileSync !== VirtualFS.prototype.writeFileSync) {
|
|
31971
|
+
const existing = this.existsSync(path2) ? this.readFileSync(path2) : new Uint8Array(0);
|
|
31972
|
+
if (data2.byteLength === 0 && this.existsSync(path2)) return;
|
|
31973
|
+
const whole = new Uint8Array(Math.max(existing.byteLength, position + data2.byteLength));
|
|
31974
|
+
whole.set(existing, 0);
|
|
31975
|
+
whole.set(data2, position);
|
|
31976
|
+
this.writeFileSync(path2, whole);
|
|
31977
|
+
return;
|
|
31978
|
+
}
|
|
31979
|
+
const normalized = this.normalizePath(path2);
|
|
31980
|
+
const node = this.getNode(normalized);
|
|
31981
|
+
if (!node) {
|
|
31982
|
+
const whole = new Uint8Array(position + data2.byteLength);
|
|
31983
|
+
whole.set(data2, position);
|
|
31984
|
+
this.writeFileSyncInternal(normalized, whole, true);
|
|
31985
|
+
return;
|
|
31986
|
+
}
|
|
31987
|
+
if (node.type !== "file") throw createNodeError("EISDIR", "open", path2);
|
|
31988
|
+
this.assertWritable(normalized, "open");
|
|
31989
|
+
if (data2.byteLength === 0) return;
|
|
31990
|
+
const current3 = node.content ?? new Uint8Array(0);
|
|
31991
|
+
const length = Math.max(current3.byteLength, position + data2.byteLength);
|
|
31992
|
+
const held = node;
|
|
31993
|
+
let room = held.room;
|
|
31994
|
+
if (!room || held.lent || current3.buffer !== room.buffer || current3.byteOffset !== 0 || room.byteLength < length) {
|
|
31995
|
+
room = new Uint8Array(Math.max(length, current3.byteLength * 2, 4096));
|
|
31996
|
+
room.set(current3, 0);
|
|
31997
|
+
held.lent = false;
|
|
31998
|
+
} else if (position > current3.byteLength) {
|
|
31999
|
+
room.fill(0, current3.byteLength, position);
|
|
32000
|
+
}
|
|
32001
|
+
room.set(data2, position);
|
|
32002
|
+
node.content = room.subarray(0, length);
|
|
32003
|
+
node.room = room;
|
|
32004
|
+
node.mtime = Date.now();
|
|
32005
|
+
this.notifyWatchers(normalized, "change");
|
|
32006
|
+
if ((_a2 = this.eventListeners.get("change")) == null ? void 0 : _a2.size) this.emit("change", normalized, this.decoder.decode(node.content));
|
|
32007
|
+
}
|
|
31936
32008
|
/**
|
|
31937
32009
|
* Create directory, optionally with recursive parent creation
|
|
31938
32010
|
*/
|
|
@@ -39655,10 +39727,28 @@ function createRequire(vfs2, fsShim, process2, currentDir, moduleCache, options,
|
|
|
39655
39727
|
}
|
|
39656
39728
|
return loadModule(resolved).exports;
|
|
39657
39729
|
};
|
|
39658
|
-
require2.resolve = (id) => {
|
|
39730
|
+
require2.resolve = (id, options2) => {
|
|
39659
39731
|
if (id === "fs" || id === "process" || id.startsWith("node:") || builtinModules$1.includes(id)) {
|
|
39660
39732
|
return id;
|
|
39661
39733
|
}
|
|
39734
|
+
if (options2 && options2.paths !== void 0) {
|
|
39735
|
+
if (!Array.isArray(options2.paths)) {
|
|
39736
|
+
throw Object.assign(new TypeError(`The property 'options.paths' must be an Array. Received ${String(options2.paths)}`), { code: "ERR_INVALID_ARG_VALUE" });
|
|
39737
|
+
}
|
|
39738
|
+
options2.paths.forEach((from, index2) => {
|
|
39739
|
+
if (typeof from !== "string") throw Object.assign(new TypeError(`The "paths[${index2}]" argument must be of type string. Received ${typeof from}`), { code: "ERR_INVALID_ARG_TYPE" });
|
|
39740
|
+
});
|
|
39741
|
+
const requireStack = parentModule && typeof parentModule.filename === "string" ? [parentModule.filename] : [];
|
|
39742
|
+
for (const from of options2.paths) {
|
|
39743
|
+
try {
|
|
39744
|
+
return resolveModule(id, resolve(process2.cwd(), from));
|
|
39745
|
+
} catch {
|
|
39746
|
+
}
|
|
39747
|
+
}
|
|
39748
|
+
throw Object.assign(new Error(`Cannot find module '${id}'${requireStack.length ? `
|
|
39749
|
+
Require stack:
|
|
39750
|
+
- ${requireStack.join("\n- ")}` : ""}`), { code: "MODULE_NOT_FOUND", requireStack });
|
|
39751
|
+
}
|
|
39662
39752
|
return resolveModule(id, currentDir);
|
|
39663
39753
|
};
|
|
39664
39754
|
require2.cache = moduleCache;
|
|
@@ -40338,7 +40428,7 @@ class WorkerRuntime {
|
|
|
40338
40428
|
this.worker = new Worker(
|
|
40339
40429
|
new URL(
|
|
40340
40430
|
/* @vite-ignore */
|
|
40341
|
-
"/assets/runtime-worker-
|
|
40431
|
+
"/assets/runtime-worker-DuSugZ3P.js",
|
|
40342
40432
|
import.meta.url
|
|
40343
40433
|
),
|
|
40344
40434
|
{ type: "module" }
|
package/dist/virtual-fs.d.ts
CHANGED
|
@@ -204,6 +204,16 @@ export declare class VirtualFS {
|
|
|
204
204
|
* read and write unless it answers appends itself.
|
|
205
205
|
*/
|
|
206
206
|
appendFileSync(path: string, data: string | Uint8Array): void;
|
|
207
|
+
/**
|
|
208
|
+
* Bytes written into a file at `position`, as a disk takes them: a gap past
|
|
209
|
+
* the end reads as zeros, and the file grows in its own buffer as an append
|
|
210
|
+
* grows it. A database rewrites its log and its pages a page at a time;
|
|
211
|
+
* writing the whole file again for each page copied Postgres's 16 MB
|
|
212
|
+
* write-ahead log at every commit. A tree that keeps its files elsewhere
|
|
213
|
+
* (its own writeFileSync) is written through its own read and write unless
|
|
214
|
+
* it answers this itself.
|
|
215
|
+
*/
|
|
216
|
+
writeAtSync(path: string, data: Uint8Array, position: number): void;
|
|
207
217
|
/**
|
|
208
218
|
* Create directory, optionally with recursive parent creation
|
|
209
219
|
*/
|
package/package.json
CHANGED
|
@@ -630,6 +630,30 @@ const fsBinding = {
|
|
|
630
630
|
if (position === null || position === undefined || position < 0) file.position = end + slice.length;
|
|
631
631
|
return slice.length;
|
|
632
632
|
}
|
|
633
|
+
// A write elsewhere in the file goes where it lands, when the tree takes one: a database's page or log
|
|
634
|
+
// record costs its own bytes, not the file's (Postgres's commits wrote its whole 16 MB log again).
|
|
635
|
+
if (typeof (tree as { writeAtSync?: unknown }).writeAtSync === 'function') {
|
|
636
|
+
const at = position === null || position === undefined || position < 0 ? file.position : position;
|
|
637
|
+
(tree as { writeAtSync(path: string, data: Uint8Array, position: number): void }).writeAtSync(file.path, slice, at);
|
|
638
|
+
// This descriptor's copy takes the same bytes, in a buffer of its own with room, as an append's does: a
|
|
639
|
+
// read after the write is answered from it rather than by reading the whole file again.
|
|
640
|
+
if (file.cached !== undefined && slice.length > 0) {
|
|
641
|
+
const cached = file.cached;
|
|
642
|
+
const length = Math.max(cached.length, at + slice.length);
|
|
643
|
+
let room = file.room;
|
|
644
|
+
if (!room || cached.buffer !== room.buffer || cached.byteOffset !== 0 || room.byteLength < length) {
|
|
645
|
+
room = new Uint8Array(Math.max(length, cached.length * 2, 4096));
|
|
646
|
+
room.set(cached, 0);
|
|
647
|
+
} else if (at > cached.length) {
|
|
648
|
+
room.fill(0, cached.length, at);
|
|
649
|
+
}
|
|
650
|
+
room.set(slice, at);
|
|
651
|
+
file.cached = room.subarray(0, length);
|
|
652
|
+
file.room = room;
|
|
653
|
+
}
|
|
654
|
+
if (position === null || position === undefined || position < 0) file.position = at + slice.length;
|
|
655
|
+
return slice.length;
|
|
656
|
+
}
|
|
633
657
|
const existing = file.cached ?? (tree.existsSync(file.path) ? tree.readFileSync(file.path) as Uint8Array : new Uint8Array(0));
|
|
634
658
|
const at = (file.flags & flagBits().append) !== 0 ? existing.length
|
|
635
659
|
: position === null || position === undefined || position < 0 ? file.position : position;
|
package/src/runtime.ts
CHANGED
|
@@ -2410,10 +2410,28 @@ function createRequire(
|
|
|
2410
2410
|
return loadModule(resolved).exports;
|
|
2411
2411
|
};
|
|
2412
2412
|
|
|
2413
|
-
require.resolve = (id: string): string => {
|
|
2413
|
+
require.resolve = (id: string, options?: { paths?: unknown }): string => {
|
|
2414
2414
|
if (id === 'fs' || id === 'process' || id.startsWith('node:') || moduleShim.builtinModules.includes(id)) {
|
|
2415
2415
|
return id;
|
|
2416
2416
|
}
|
|
2417
|
+
// Node's `options.paths`: each directory, in order, is where the lookup starts, as if the request came from a
|
|
2418
|
+
// module there, and the first that resolves wins. The option was ignored and every lookup started at the caller,
|
|
2419
|
+
// so a module installed in one tree could not find a package another tree holds (a World's injector resolving
|
|
2420
|
+
// the application's own Prisma adapter from the application's directory). Node 12.
|
|
2421
|
+
if (options && options.paths !== undefined) {
|
|
2422
|
+
if (!Array.isArray(options.paths)) {
|
|
2423
|
+
throw Object.assign(new TypeError(`The property 'options.paths' must be an Array. Received ${String(options.paths)}`), { code: 'ERR_INVALID_ARG_VALUE' });
|
|
2424
|
+
}
|
|
2425
|
+
options.paths.forEach((from, index) => {
|
|
2426
|
+
if (typeof from !== 'string') throw Object.assign(new TypeError(`The "paths[${index}]" argument must be of type string. Received ${typeof from}`), { code: 'ERR_INVALID_ARG_TYPE' });
|
|
2427
|
+
});
|
|
2428
|
+
// A relative entry is the process's working directory's, as Node's Module._resolveFilename makes it.
|
|
2429
|
+
const requireStack = parentModule && typeof parentModule.filename === 'string' ? [parentModule.filename] : [];
|
|
2430
|
+
for (const from of options.paths as string[]) {
|
|
2431
|
+
try { return resolveModule(id, pathShim.resolve(process.cwd(), from)); } catch { /* the next directory */ }
|
|
2432
|
+
}
|
|
2433
|
+
throw Object.assign(new Error(`Cannot find module '${id}'${requireStack.length ? `\nRequire stack:\n- ${requireStack.join('\n- ')}` : ''}`), { code: 'MODULE_NOT_FOUND', requireStack });
|
|
2434
|
+
}
|
|
2417
2435
|
return resolveModule(id, currentDir);
|
|
2418
2436
|
};
|
|
2419
2437
|
|
package/src/virtual-fs.ts
CHANGED
|
@@ -324,6 +324,9 @@ export class VirtualFS {
|
|
|
324
324
|
if (existed && existing!.type === 'file') {
|
|
325
325
|
existing!.content = content;
|
|
326
326
|
existing!.mtime = Date.now();
|
|
327
|
+
// the caller's bytes, which it may still hold: never written in place
|
|
328
|
+
(existing as FSNode & { room?: Uint8Array; lent?: boolean }).room = undefined;
|
|
329
|
+
(existing as FSNode & { lent?: boolean }).lent = true;
|
|
327
330
|
} else {
|
|
328
331
|
parent.children!.set(basename, {
|
|
329
332
|
type: 'file',
|
|
@@ -646,6 +649,10 @@ export class VirtualFS {
|
|
|
646
649
|
return this.decoder.decode(content);
|
|
647
650
|
}
|
|
648
651
|
|
|
652
|
+
// The bytes are handed out as they are, so a caller (a copy, a read
|
|
653
|
+
// stream's chunk) may hold them: a later write into the file does not
|
|
654
|
+
// change them in place (writeAtSync), it moves the file to bytes of its own.
|
|
655
|
+
(node as FSNode & { lent?: boolean }).lent = true;
|
|
649
656
|
return content;
|
|
650
657
|
}
|
|
651
658
|
|
|
@@ -698,6 +705,58 @@ export class VirtualFS {
|
|
|
698
705
|
if (this.eventListeners.get('change')?.size) this.emit('change', normalized, this.decoder.decode(node.content));
|
|
699
706
|
}
|
|
700
707
|
|
|
708
|
+
/**
|
|
709
|
+
* Bytes written into a file at `position`, as a disk takes them: a gap past
|
|
710
|
+
* the end reads as zeros, and the file grows in its own buffer as an append
|
|
711
|
+
* grows it. A database rewrites its log and its pages a page at a time;
|
|
712
|
+
* writing the whole file again for each page copied Postgres's 16 MB
|
|
713
|
+
* write-ahead log at every commit. A tree that keeps its files elsewhere
|
|
714
|
+
* (its own writeFileSync) is written through its own read and write unless
|
|
715
|
+
* it answers this itself.
|
|
716
|
+
*/
|
|
717
|
+
writeAtSync(path: string, data: Uint8Array, position: number): void {
|
|
718
|
+
if (this.writeFileSync !== VirtualFS.prototype.writeFileSync) {
|
|
719
|
+
const existing = this.existsSync(path) ? this.readFileSync(path) as Uint8Array : new Uint8Array(0);
|
|
720
|
+
if (data.byteLength === 0 && this.existsSync(path)) return;
|
|
721
|
+
const whole = new Uint8Array(Math.max(existing.byteLength, position + data.byteLength));
|
|
722
|
+
whole.set(existing, 0);
|
|
723
|
+
whole.set(data, position);
|
|
724
|
+
this.writeFileSync(path, whole);
|
|
725
|
+
return;
|
|
726
|
+
}
|
|
727
|
+
const normalized = this.normalizePath(path);
|
|
728
|
+
const node = this.getNode(normalized);
|
|
729
|
+
if (!node) {
|
|
730
|
+
const whole = new Uint8Array(position + data.byteLength);
|
|
731
|
+
whole.set(data, position);
|
|
732
|
+
this.writeFileSyncInternal(normalized, whole, true);
|
|
733
|
+
return;
|
|
734
|
+
}
|
|
735
|
+
if (node.type !== 'file') throw createNodeError('EISDIR', 'open', path);
|
|
736
|
+
this.assertWritable(normalized, 'open');
|
|
737
|
+
// Node's write of no bytes changes nothing, past the end included
|
|
738
|
+
if (data.byteLength === 0) return;
|
|
739
|
+
const current = node.content ?? new Uint8Array(0);
|
|
740
|
+
const length = Math.max(current.byteLength, position + data.byteLength);
|
|
741
|
+
const held = node as FSNode & { room?: Uint8Array; lent?: boolean };
|
|
742
|
+
let room = held.room;
|
|
743
|
+
// Written in place only into bytes the file owns and nobody else holds: a copy made from the file
|
|
744
|
+
// (writeFileSync(dest, readFileSync(src))) or a read's result shares them, and would change with it.
|
|
745
|
+
if (!room || held.lent || current.buffer !== room.buffer || current.byteOffset !== 0 || room.byteLength < length) {
|
|
746
|
+
room = new Uint8Array(Math.max(length, current.byteLength * 2, 4096));
|
|
747
|
+
room.set(current, 0);
|
|
748
|
+
held.lent = false;
|
|
749
|
+
} else if (position > current.byteLength) {
|
|
750
|
+
room.fill(0, current.byteLength, position);
|
|
751
|
+
}
|
|
752
|
+
room.set(data, position);
|
|
753
|
+
node.content = room.subarray(0, length);
|
|
754
|
+
(node as FSNode & { room?: Uint8Array }).room = room;
|
|
755
|
+
node.mtime = Date.now();
|
|
756
|
+
this.notifyWatchers(normalized, 'change');
|
|
757
|
+
if (this.eventListeners.get('change')?.size) this.emit('change', normalized, this.decoder.decode(node.content));
|
|
758
|
+
}
|
|
759
|
+
|
|
701
760
|
/**
|
|
702
761
|
* Create directory, optionally with recursive parent creation
|
|
703
762
|
*/
|