@ccheever/exact-ibex-runtime 0.1.0
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/package.json +63 -0
- package/src/abort/AbortController.ts +23 -0
- package/src/abort/AbortSignal.ts +152 -0
- package/src/abort/index.ts +2 -0
- package/src/accessibility.ts +12 -0
- package/src/arraybuffer-detach.ts +109 -0
- package/src/base64/base64.ts +168 -0
- package/src/base64/index.ts +1 -0
- package/src/blob/Blob.ts +259 -0
- package/src/blob/File.ts +59 -0
- package/src/blob/FormData.ts +323 -0
- package/src/blob/index.ts +3 -0
- package/src/bootstrap.ts +1946 -0
- package/src/broadcast/BroadcastChannel.ts +280 -0
- package/src/broadcast/index.ts +5 -0
- package/src/cache/Cache.ts +349 -0
- package/src/cache/CacheStorage.ts +89 -0
- package/src/cache/index.ts +27 -0
- package/src/camera/index.ts +6202 -0
- package/src/camera/processor.worker.ts +194 -0
- package/src/camera/scene.ts +195 -0
- package/src/clipboard/Clipboard.ts +129 -0
- package/src/clipboard/ClipboardItem.ts +97 -0
- package/src/clipboard/index.ts +6 -0
- package/src/clone/index.ts +1 -0
- package/src/clone/structuredClone.ts +389 -0
- package/src/clone/transferableSymbols.ts +2 -0
- package/src/compression/CompressionStream.ts +146 -0
- package/src/compression/DecompressionStream.ts +342 -0
- package/src/compression/index.ts +4 -0
- package/src/console/Console.ts +341 -0
- package/src/console/index.ts +2 -0
- package/src/core/accessibility-state.ts +263 -0
- package/src/core/accessibility.ts +184 -0
- package/src/core/agent-state.ts +37 -0
- package/src/core/diagnostics-logs.ts +144 -0
- package/src/core/host-call-bridge.ts +16 -0
- package/src/core/i18n-helpers.ts +189 -0
- package/src/core/locale-state.ts +253 -0
- package/src/core/locale.ts +95 -0
- package/src/crypto/Crypto.ts +2743 -0
- package/src/crypto/index.ts +1 -0
- package/src/diagnostics/logs.ts +7 -0
- package/src/encoding/TextDecoder.ts +1181 -0
- package/src/encoding/TextDecoderStream.ts +58 -0
- package/src/encoding/TextEncoder.ts +180 -0
- package/src/encoding/TextEncoderStream.ts +39 -0
- package/src/encoding/index.ts +8 -0
- package/src/events/CloseEvent.ts +91 -0
- package/src/events/DOMException.ts +409 -0
- package/src/events/ErrorEvent.ts +39 -0
- package/src/events/Event.ts +151 -0
- package/src/events/EventTarget.ts +280 -0
- package/src/events/FocusEvent.ts +27 -0
- package/src/events/KeyboardEvent.ts +46 -0
- package/src/events/MessageEvent.ts +61 -0
- package/src/events/ProgressEvent.ts +33 -0
- package/src/events/PromiseRejectionEvent.ts +31 -0
- package/src/events/index.ts +52 -0
- package/src/eventsource/EventSource.ts +371 -0
- package/src/eventsource/index.ts +2 -0
- package/src/fetch/Headers.ts +642 -0
- package/src/fetch/Request.ts +760 -0
- package/src/fetch/Response.ts +543 -0
- package/src/fetch/body.ts +1256 -0
- package/src/fetch/cookie-jar.ts +566 -0
- package/src/fetch/demo.ts +207 -0
- package/src/fetch/errors.ts +101 -0
- package/src/fetch/fetch.ts +2610 -0
- package/src/fetch/index.ts +101 -0
- package/src/fetch/native-bridge.ts +65 -0
- package/src/fetch/types.ts +258 -0
- package/src/filereader/FileReader.ts +236 -0
- package/src/filereader/index.ts +1 -0
- package/src/fs/Dirent.ts +39 -0
- package/src/fs/ExactFile.ts +450 -0
- package/src/fs/Stats.ts +80 -0
- package/src/fs/index.ts +944 -0
- package/src/fs/promises.ts +386 -0
- package/src/fs/shared.ts +328 -0
- package/src/http-server/index.js +697 -0
- package/src/http-server/index.ts +27 -0
- package/src/identity.generated.ts +14 -0
- package/src/index.ts +283 -0
- package/src/indexeddb/IDBCursor.ts +188 -0
- package/src/indexeddb/IDBDatabase.ts +343 -0
- package/src/indexeddb/IDBFactory.ts +269 -0
- package/src/indexeddb/IDBIndex.ts +194 -0
- package/src/indexeddb/IDBKeyRange.ts +109 -0
- package/src/indexeddb/IDBObjectStore.ts +468 -0
- package/src/indexeddb/IDBRequest.ts +163 -0
- package/src/indexeddb/IDBTransaction.ts +207 -0
- package/src/indexeddb/index.ts +34 -0
- package/src/indexeddb/utils.ts +52 -0
- package/src/inspect/index.ts +1 -0
- package/src/inspect/inspect.ts +465 -0
- package/src/internal/detect.ts +104 -0
- package/src/locale.ts +10 -0
- package/src/location/index.ts +1059 -0
- package/src/locks/LockManager.ts +460 -0
- package/src/locks/index.ts +12 -0
- package/src/media/VideoFrame.ts +58 -0
- package/src/messaging/MessageChannel.ts +31 -0
- package/src/messaging/MessagePort.ts +180 -0
- package/src/messaging/index.ts +2 -0
- package/src/messaging.ts +247 -0
- package/src/native/NativeModules.ts +354 -0
- package/src/native/index.ts +1 -0
- package/src/navigator/Navigator.ts +351 -0
- package/src/navigator/index.ts +1 -0
- package/src/node/Buffer.ts +1786 -0
- package/src/node/index.ts +4 -0
- package/src/node/path.ts +495 -0
- package/src/node/process.ts +2528 -0
- package/src/performance/Performance.ts +532 -0
- package/src/performance/index.ts +21 -0
- package/src/polyfills/array.ts +236 -0
- package/src/polyfills/arraybuffer.ts +172 -0
- package/src/polyfills/groupby.ts +85 -0
- package/src/polyfills/index.ts +85 -0
- package/src/polyfills/intl.ts +1956 -0
- package/src/polyfills/iterator.ts +479 -0
- package/src/polyfills/promise.ts +37 -0
- package/src/polyfills/set.ts +245 -0
- package/src/polyfills/string.ts +85 -0
- package/src/polyfills/typedarray.ts +110 -0
- package/src/promise-rejection-tracking.ts +464 -0
- package/src/react-native/index.ts +388 -0
- package/src/runtime-entry.ts +55 -0
- package/src/scheduling/AnimationFrame.ts +105 -0
- package/src/scheduling/IdleCallback.ts +167 -0
- package/src/scheduling/index.ts +13 -0
- package/src/security/Capabilities.ts +1146 -0
- package/src/security/Permissions.ts +392 -0
- package/src/security/capability-bits.generated.ts +63 -0
- package/src/security/index.ts +16 -0
- package/src/sqlite/Database.ts +456 -0
- package/src/sqlite/Statement.ts +206 -0
- package/src/sqlite/constants.ts +79 -0
- package/src/sqlite/errors.ts +25 -0
- package/src/sqlite/index.ts +34 -0
- package/src/sqlite/module.js +438 -0
- package/src/storage/Storage.ts +291 -0
- package/src/storage/StorageManager.ts +91 -0
- package/src/storage/index.ts +3 -0
- package/src/stream-compat.ts +47 -0
- package/src/streams/ReadableStream.ts +4131 -0
- package/src/streams/TransformStream.ts +375 -0
- package/src/streams/WritableStream.ts +866 -0
- package/src/streams/index.ts +41 -0
- package/src/timers/Timers.ts +296 -0
- package/src/timers/index.ts +11 -0
- package/src/url/URL.ts +656 -0
- package/src/url/URLPattern.ts +850 -0
- package/src/url/URLSearchParams.ts +244 -0
- package/src/url/index.ts +9 -0
- package/src/websocket/WebSocket.ts +770 -0
- package/src/websocket/WebSocketError.ts +52 -0
- package/src/websocket/WebSocketStream.ts +628 -0
- package/src/websocket/index.ts +7 -0
- package/src/window/index.ts +872 -0
package/src/fs/index.ts
ADDED
|
@@ -0,0 +1,944 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Node.js-compatible fs module.
|
|
3
|
+
*
|
|
4
|
+
* Provides callback-based and sync variants of filesystem operations.
|
|
5
|
+
* Built on the __exact* globals provided by the C++ Hermes bridge.
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
import { join } from '../node/path';
|
|
9
|
+
import { Dirent } from './Dirent';
|
|
10
|
+
import { Stats } from './Stats';
|
|
11
|
+
import * as promises from './promises';
|
|
12
|
+
import {
|
|
13
|
+
accessNative,
|
|
14
|
+
appendFileBytes,
|
|
15
|
+
chmodNative,
|
|
16
|
+
closeFileDescriptor,
|
|
17
|
+
constants,
|
|
18
|
+
copyFileNative,
|
|
19
|
+
decodeBytes,
|
|
20
|
+
mkdtempNative,
|
|
21
|
+
mkdirNative,
|
|
22
|
+
openFileDescriptor,
|
|
23
|
+
parseReaddir,
|
|
24
|
+
queueTask,
|
|
25
|
+
readFileBytes,
|
|
26
|
+
readFileDescriptor,
|
|
27
|
+
realpathNative,
|
|
28
|
+
renameNative,
|
|
29
|
+
rmdirNative,
|
|
30
|
+
statJson,
|
|
31
|
+
toStats,
|
|
32
|
+
toUint8Array,
|
|
33
|
+
type Callback,
|
|
34
|
+
type FileData,
|
|
35
|
+
type ReadCallback,
|
|
36
|
+
type WriteCallback,
|
|
37
|
+
unlinkNative,
|
|
38
|
+
wrapBuffer,
|
|
39
|
+
wrapCallback,
|
|
40
|
+
writeFileBytes,
|
|
41
|
+
writeFileDescriptor,
|
|
42
|
+
lstatJson,
|
|
43
|
+
symlinkNative,
|
|
44
|
+
linkNative,
|
|
45
|
+
readlinkNative,
|
|
46
|
+
truncateNative,
|
|
47
|
+
utimesNative,
|
|
48
|
+
} from './shared';
|
|
49
|
+
|
|
50
|
+
export { Dirent, Stats, promises, constants };
|
|
51
|
+
|
|
52
|
+
const VALID_SYMLINK_TYPES = new Set(['dir', 'file', 'junction']);
|
|
53
|
+
|
|
54
|
+
function describeArgValue(value: unknown): string {
|
|
55
|
+
if (value === null) {
|
|
56
|
+
return 'null';
|
|
57
|
+
}
|
|
58
|
+
if (value === undefined) {
|
|
59
|
+
return 'undefined';
|
|
60
|
+
}
|
|
61
|
+
if (Array.isArray(value)) {
|
|
62
|
+
return 'an instance of Array';
|
|
63
|
+
}
|
|
64
|
+
if (typeof value === 'function') {
|
|
65
|
+
return value.name ? `function ${value.name}` : 'function';
|
|
66
|
+
}
|
|
67
|
+
if (typeof value === 'object') {
|
|
68
|
+
const ctorName = (value as { constructor?: { name?: string } }).constructor?.name ?? 'Object';
|
|
69
|
+
return `an instance of ${ctorName}`;
|
|
70
|
+
}
|
|
71
|
+
if (typeof value === 'string') {
|
|
72
|
+
return `type string (${value})`;
|
|
73
|
+
}
|
|
74
|
+
if (typeof value === 'number') {
|
|
75
|
+
return `type number (${value})`;
|
|
76
|
+
}
|
|
77
|
+
if (typeof value === 'boolean') {
|
|
78
|
+
return `type boolean (${value})`;
|
|
79
|
+
}
|
|
80
|
+
if (typeof value === 'symbol') {
|
|
81
|
+
return `type symbol (${String(value)})`;
|
|
82
|
+
}
|
|
83
|
+
return `type ${typeof value}`;
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
function assignErrorCode<T extends Error>(error: T, code: string): T {
|
|
87
|
+
(error as T & { code: string }).code = code;
|
|
88
|
+
return error;
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
function makeInvalidArgTypeError(name: string, value: unknown): TypeError {
|
|
92
|
+
return assignErrorCode(
|
|
93
|
+
new TypeError(
|
|
94
|
+
`The "${name}" argument must be of type string or an instance of Buffer or URL. Received ${describeArgValue(value)}`,
|
|
95
|
+
),
|
|
96
|
+
'ERR_INVALID_ARG_TYPE',
|
|
97
|
+
);
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
function makeInvalidArgValueError(name: string, value: unknown, reason: string): TypeError {
|
|
101
|
+
let received: string;
|
|
102
|
+
if (typeof value === 'string') {
|
|
103
|
+
received = `'${value}'`;
|
|
104
|
+
} else if (value === undefined) {
|
|
105
|
+
received = 'undefined';
|
|
106
|
+
} else if (value === null) {
|
|
107
|
+
received = 'null';
|
|
108
|
+
} else {
|
|
109
|
+
received = String(value);
|
|
110
|
+
}
|
|
111
|
+
return assignErrorCode(
|
|
112
|
+
new TypeError(`The argument "${name}" must be ${reason}. Received ${received}`),
|
|
113
|
+
'ERR_INVALID_ARG_VALUE',
|
|
114
|
+
);
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
function makeInvalidUrlSchemeError(): TypeError {
|
|
118
|
+
return assignErrorCode(new TypeError('The URL must be of scheme file'), 'ERR_INVALID_URL_SCHEME');
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
function arrayBufferViewToString(view: ArrayBufferView): string {
|
|
122
|
+
if (typeof Buffer !== 'undefined') {
|
|
123
|
+
return Buffer.from(view.buffer, view.byteOffset, view.byteLength).toString();
|
|
124
|
+
}
|
|
125
|
+
const bytes = new Uint8Array(view.buffer, view.byteOffset, view.byteLength);
|
|
126
|
+
if (typeof TextDecoder !== 'undefined') {
|
|
127
|
+
return new TextDecoder().decode(bytes);
|
|
128
|
+
}
|
|
129
|
+
let result = '';
|
|
130
|
+
for (let i = 0; i < bytes.length; i++) {
|
|
131
|
+
result += String.fromCharCode(bytes[i]);
|
|
132
|
+
}
|
|
133
|
+
return result;
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
function toPathString(value: unknown, name: string): string {
|
|
137
|
+
if (typeof value === 'string') {
|
|
138
|
+
return value;
|
|
139
|
+
}
|
|
140
|
+
if (typeof Buffer !== 'undefined' && Buffer.isBuffer(value)) {
|
|
141
|
+
return value.toString();
|
|
142
|
+
}
|
|
143
|
+
if (typeof ArrayBuffer !== 'undefined' && typeof ArrayBuffer.isView === 'function' && ArrayBuffer.isView(value)) {
|
|
144
|
+
return arrayBufferViewToString(value);
|
|
145
|
+
}
|
|
146
|
+
if (value && typeof value === 'object' && typeof (value as { href?: unknown }).href === 'string') {
|
|
147
|
+
const url = value as { protocol?: unknown; pathname?: unknown };
|
|
148
|
+
if (url.protocol !== 'file:') {
|
|
149
|
+
throw makeInvalidUrlSchemeError();
|
|
150
|
+
}
|
|
151
|
+
let pathname = typeof url.pathname === 'string' ? url.pathname : '';
|
|
152
|
+
if (
|
|
153
|
+
pathname.length >= 3 &&
|
|
154
|
+
pathname[0] === '/' &&
|
|
155
|
+
pathname[2] === ':' &&
|
|
156
|
+
/[A-Za-z]/.test(pathname[1])
|
|
157
|
+
) {
|
|
158
|
+
pathname = pathname.slice(1);
|
|
159
|
+
}
|
|
160
|
+
return decodeURIComponent(pathname);
|
|
161
|
+
}
|
|
162
|
+
throw makeInvalidArgTypeError(name, value);
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
function validateSymlinkType(type: unknown): void {
|
|
166
|
+
if (type === undefined) {
|
|
167
|
+
return;
|
|
168
|
+
}
|
|
169
|
+
if (typeof type !== 'string' || !VALID_SYMLINK_TYPES.has(type)) {
|
|
170
|
+
throw makeInvalidArgValueError('type', type, "one of: 'dir', 'file', 'junction', or undefined");
|
|
171
|
+
}
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
function normalizeUtimesValue(value: number | Date | string): number {
|
|
175
|
+
if (value instanceof Date) {
|
|
176
|
+
return value.getTime() / 1000;
|
|
177
|
+
}
|
|
178
|
+
if (typeof value === 'string') {
|
|
179
|
+
return Number(value);
|
|
180
|
+
}
|
|
181
|
+
return value;
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
function normalizeRmError<T>(error: T, path?: string, recursive = false): T {
|
|
185
|
+
if (!error || typeof error !== 'object') {
|
|
186
|
+
return error;
|
|
187
|
+
}
|
|
188
|
+
const fsError = error as { syscall?: string; message?: string; code?: string; path?: string };
|
|
189
|
+
if (fsError.syscall === 'rmdir' || fsError.syscall === 'unlink') {
|
|
190
|
+
fsError.syscall = 'rm';
|
|
191
|
+
if (typeof fsError.message === 'string') {
|
|
192
|
+
fsError.message = fsError.message.replace(/, (?:rmdir|unlink) /, ', rm ');
|
|
193
|
+
}
|
|
194
|
+
}
|
|
195
|
+
if (
|
|
196
|
+
recursive &&
|
|
197
|
+
typeof process !== 'undefined' &&
|
|
198
|
+
process.platform === 'darwin' &&
|
|
199
|
+
fsError.code === 'EACCES'
|
|
200
|
+
) {
|
|
201
|
+
fsError.code = 'ENOTEMPTY';
|
|
202
|
+
fsError.path = path ?? fsError.path;
|
|
203
|
+
if (path) {
|
|
204
|
+
fsError.message = `ENOTEMPTY: directory not empty, rm '${path}'`;
|
|
205
|
+
}
|
|
206
|
+
}
|
|
207
|
+
return error;
|
|
208
|
+
}
|
|
209
|
+
|
|
210
|
+
class EventEmitter {
|
|
211
|
+
private listeners: Record<string, Array<{ fn: (...args: any[]) => void; once: boolean }>> = {};
|
|
212
|
+
|
|
213
|
+
on(event: string, listener: (...args: any[]) => void): this {
|
|
214
|
+
(this.listeners[event] ??= []).push({ fn: listener, once: false });
|
|
215
|
+
return this;
|
|
216
|
+
}
|
|
217
|
+
|
|
218
|
+
addListener(event: string, listener: (...args: any[]) => void): this {
|
|
219
|
+
return this.on(event, listener);
|
|
220
|
+
}
|
|
221
|
+
|
|
222
|
+
once(event: string, listener: (...args: any[]) => void): this {
|
|
223
|
+
(this.listeners[event] ??= []).push({ fn: listener, once: true });
|
|
224
|
+
return this;
|
|
225
|
+
}
|
|
226
|
+
|
|
227
|
+
emit(event: string, ...args: any[]): boolean {
|
|
228
|
+
const listeners = this.listeners[event];
|
|
229
|
+
if (!listeners || listeners.length === 0) {
|
|
230
|
+
return false;
|
|
231
|
+
}
|
|
232
|
+
this.listeners[event] = listeners.filter((entry) => {
|
|
233
|
+
entry.fn(...args);
|
|
234
|
+
return !entry.once;
|
|
235
|
+
});
|
|
236
|
+
return true;
|
|
237
|
+
}
|
|
238
|
+
|
|
239
|
+
removeListener(event: string, listener: (...args: any[]) => void): this {
|
|
240
|
+
this.listeners[event] = (this.listeners[event] ?? []).filter((entry) => entry.fn !== listener);
|
|
241
|
+
return this;
|
|
242
|
+
}
|
|
243
|
+
}
|
|
244
|
+
|
|
245
|
+
class ReadStream extends EventEmitter {
|
|
246
|
+
readonly path: string;
|
|
247
|
+
readonly flags: string | number;
|
|
248
|
+
readonly highWaterMark: number;
|
|
249
|
+
readonly encoding?: string;
|
|
250
|
+
readonly autoClose: boolean;
|
|
251
|
+
private fd: number | null;
|
|
252
|
+
private cursor: number;
|
|
253
|
+
private readonly end: number | null;
|
|
254
|
+
destroyed = false;
|
|
255
|
+
|
|
256
|
+
constructor(path: string, options: { flags?: string | number; encoding?: string; fd?: number; autoClose?: boolean; highWaterMark?: number; start?: number; end?: number } = {}) {
|
|
257
|
+
super();
|
|
258
|
+
this.path = path;
|
|
259
|
+
this.flags = options.flags ?? 'r';
|
|
260
|
+
this.encoding = options.encoding;
|
|
261
|
+
this.fd = options.fd ?? null;
|
|
262
|
+
this.autoClose = options.autoClose ?? true;
|
|
263
|
+
this.highWaterMark = options.highWaterMark ?? 64 * 1024;
|
|
264
|
+
this.cursor = options.start ?? 0;
|
|
265
|
+
this.end = options.end ?? null;
|
|
266
|
+
|
|
267
|
+
queueTask(() => this.startReading());
|
|
268
|
+
}
|
|
269
|
+
|
|
270
|
+
pipe(destination: { write: (chunk: any) => any; end?: () => void; emit?: (...args: any[]) => void; destroy?: (err?: unknown) => void }): typeof destination {
|
|
271
|
+
this.on('data', (chunk) => {
|
|
272
|
+
destination.write(chunk);
|
|
273
|
+
});
|
|
274
|
+
this.once('end', () => {
|
|
275
|
+
destination.end?.();
|
|
276
|
+
});
|
|
277
|
+
this.once('error', (error) => {
|
|
278
|
+
if (typeof destination.emit === 'function') {
|
|
279
|
+
destination.emit('error', error);
|
|
280
|
+
} else {
|
|
281
|
+
destination.destroy?.(error);
|
|
282
|
+
}
|
|
283
|
+
});
|
|
284
|
+
return destination;
|
|
285
|
+
}
|
|
286
|
+
|
|
287
|
+
destroy(error?: unknown): this {
|
|
288
|
+
if (this.destroyed) {
|
|
289
|
+
return this;
|
|
290
|
+
}
|
|
291
|
+
this.destroyed = true;
|
|
292
|
+
if (this.autoClose && this.fd !== null) {
|
|
293
|
+
try {
|
|
294
|
+
closeFileDescriptor(this.fd);
|
|
295
|
+
} catch {}
|
|
296
|
+
this.fd = null;
|
|
297
|
+
}
|
|
298
|
+
if (error !== undefined) {
|
|
299
|
+
this.emit('error', error);
|
|
300
|
+
}
|
|
301
|
+
this.emit('close');
|
|
302
|
+
return this;
|
|
303
|
+
}
|
|
304
|
+
|
|
305
|
+
private startReading(): void {
|
|
306
|
+
if (this.destroyed) {
|
|
307
|
+
return;
|
|
308
|
+
}
|
|
309
|
+
|
|
310
|
+
try {
|
|
311
|
+
if (this.fd === null) {
|
|
312
|
+
this.fd = openFileDescriptor(this.path, this.flags);
|
|
313
|
+
this.emit('open', this.fd);
|
|
314
|
+
}
|
|
315
|
+
|
|
316
|
+
while (!this.destroyed) {
|
|
317
|
+
let length = this.highWaterMark;
|
|
318
|
+
if (this.end !== null) {
|
|
319
|
+
const remaining = this.end - this.cursor + 1;
|
|
320
|
+
if (remaining <= 0) {
|
|
321
|
+
break;
|
|
322
|
+
}
|
|
323
|
+
length = Math.min(length, remaining);
|
|
324
|
+
}
|
|
325
|
+
|
|
326
|
+
const chunk = readFileDescriptor(this.fd, length, this.cursor);
|
|
327
|
+
if (chunk.byteLength === 0) {
|
|
328
|
+
break;
|
|
329
|
+
}
|
|
330
|
+
this.cursor += chunk.byteLength;
|
|
331
|
+
this.emit('data', this.encoding ? decodeBytes(chunk, this.encoding) : wrapBuffer(chunk));
|
|
332
|
+
}
|
|
333
|
+
|
|
334
|
+
if (!this.destroyed) {
|
|
335
|
+
this.emit('end');
|
|
336
|
+
}
|
|
337
|
+
this.destroy();
|
|
338
|
+
} catch (error) {
|
|
339
|
+
this.destroy(error);
|
|
340
|
+
}
|
|
341
|
+
}
|
|
342
|
+
}
|
|
343
|
+
|
|
344
|
+
class WriteStream extends EventEmitter {
|
|
345
|
+
readonly path: string;
|
|
346
|
+
readonly flags: string | number;
|
|
347
|
+
readonly autoClose: boolean;
|
|
348
|
+
private fd: number | null;
|
|
349
|
+
private cursor: number | null;
|
|
350
|
+
destroyed = false;
|
|
351
|
+
|
|
352
|
+
constructor(path: string, options: { flags?: string | number; fd?: number; autoClose?: boolean; start?: number } = {}) {
|
|
353
|
+
super();
|
|
354
|
+
this.path = path;
|
|
355
|
+
this.flags = options.flags ?? 'w';
|
|
356
|
+
this.fd = options.fd ?? null;
|
|
357
|
+
this.autoClose = options.autoClose ?? true;
|
|
358
|
+
this.cursor = options.start ?? null;
|
|
359
|
+
|
|
360
|
+
queueTask(() => {
|
|
361
|
+
try {
|
|
362
|
+
if (this.fd === null) {
|
|
363
|
+
this.fd = openFileDescriptor(this.path, this.flags);
|
|
364
|
+
}
|
|
365
|
+
this.emit('open', this.fd);
|
|
366
|
+
} catch (error) {
|
|
367
|
+
this.destroy(error);
|
|
368
|
+
}
|
|
369
|
+
});
|
|
370
|
+
}
|
|
371
|
+
|
|
372
|
+
write(chunk: FileData, callback?: (err?: Error | null) => void): boolean {
|
|
373
|
+
if (this.destroyed) {
|
|
374
|
+
callback?.(new Error('WriteStream is destroyed'));
|
|
375
|
+
return false;
|
|
376
|
+
}
|
|
377
|
+
|
|
378
|
+
try {
|
|
379
|
+
if (this.fd === null) {
|
|
380
|
+
this.fd = openFileDescriptor(this.path, this.flags);
|
|
381
|
+
this.emit('open', this.fd);
|
|
382
|
+
}
|
|
383
|
+
const bytes = toUint8Array(chunk);
|
|
384
|
+
const written = writeFileDescriptor(this.fd, bytes, this.cursor);
|
|
385
|
+
if (this.cursor !== null) {
|
|
386
|
+
this.cursor += written;
|
|
387
|
+
}
|
|
388
|
+
callback?.(null);
|
|
389
|
+
this.emit('drain');
|
|
390
|
+
return true;
|
|
391
|
+
} catch (error) {
|
|
392
|
+
const err = error instanceof Error ? error : new Error(String(error));
|
|
393
|
+
callback?.(err);
|
|
394
|
+
this.destroy(err);
|
|
395
|
+
return false;
|
|
396
|
+
}
|
|
397
|
+
}
|
|
398
|
+
|
|
399
|
+
end(chunk?: FileData, callback?: () => void): this {
|
|
400
|
+
if (chunk !== undefined) {
|
|
401
|
+
this.write(chunk);
|
|
402
|
+
}
|
|
403
|
+
if (this.autoClose && this.fd !== null) {
|
|
404
|
+
closeFileDescriptor(this.fd);
|
|
405
|
+
this.fd = null;
|
|
406
|
+
}
|
|
407
|
+
this.emit('finish');
|
|
408
|
+
this.emit('close');
|
|
409
|
+
callback?.();
|
|
410
|
+
this.destroyed = true;
|
|
411
|
+
return this;
|
|
412
|
+
}
|
|
413
|
+
|
|
414
|
+
destroy(error?: unknown): this {
|
|
415
|
+
if (this.destroyed) {
|
|
416
|
+
return this;
|
|
417
|
+
}
|
|
418
|
+
this.destroyed = true;
|
|
419
|
+
if (this.autoClose && this.fd !== null) {
|
|
420
|
+
try {
|
|
421
|
+
closeFileDescriptor(this.fd);
|
|
422
|
+
} catch {}
|
|
423
|
+
this.fd = null;
|
|
424
|
+
}
|
|
425
|
+
if (error !== undefined) {
|
|
426
|
+
this.emit('error', error);
|
|
427
|
+
}
|
|
428
|
+
this.emit('close');
|
|
429
|
+
return this;
|
|
430
|
+
}
|
|
431
|
+
}
|
|
432
|
+
|
|
433
|
+
export function readFileSync(path: string, options?: { encoding?: string } | string): Uint8Array | Buffer | string {
|
|
434
|
+
const encoding = typeof options === 'string' ? options : options?.encoding;
|
|
435
|
+
const bytes = readFileBytes(path);
|
|
436
|
+
return encoding ? decodeBytes(bytes, encoding) : wrapBuffer(bytes);
|
|
437
|
+
}
|
|
438
|
+
|
|
439
|
+
export function writeFileSync(path: string, data: FileData, _options?: { encoding?: string } | string): void {
|
|
440
|
+
writeFileBytes(path, toUint8Array(data));
|
|
441
|
+
}
|
|
442
|
+
|
|
443
|
+
export function appendFileSync(path: string, data: FileData, _options?: { encoding?: string } | string): void {
|
|
444
|
+
appendFileBytes(path, toUint8Array(data));
|
|
445
|
+
}
|
|
446
|
+
|
|
447
|
+
export function statSync(path: string): Stats {
|
|
448
|
+
return toStats(statJson(path));
|
|
449
|
+
}
|
|
450
|
+
|
|
451
|
+
export function lstatSync(path: string): Stats {
|
|
452
|
+
return toStats(lstatJson(path));
|
|
453
|
+
}
|
|
454
|
+
|
|
455
|
+
export function readdirSync(path: string, options?: { withFileTypes?: boolean }): string[] | Dirent[] {
|
|
456
|
+
return parseReaddir(path, options?.withFileTypes) as string[] | Dirent[];
|
|
457
|
+
}
|
|
458
|
+
|
|
459
|
+
export function mkdirSync(path: string, options?: { recursive?: boolean } | number): void {
|
|
460
|
+
const recursive = typeof options === 'object' && options !== null ? !!options.recursive : false;
|
|
461
|
+
mkdirNative(path, recursive);
|
|
462
|
+
}
|
|
463
|
+
|
|
464
|
+
export function rmdirSync(path: string): void {
|
|
465
|
+
rmdirNative(path);
|
|
466
|
+
}
|
|
467
|
+
|
|
468
|
+
export function unlinkSync(path: string): void {
|
|
469
|
+
unlinkNative(path);
|
|
470
|
+
}
|
|
471
|
+
|
|
472
|
+
export function renameSync(oldPath: string, newPath: string): void {
|
|
473
|
+
renameNative(oldPath, newPath);
|
|
474
|
+
}
|
|
475
|
+
|
|
476
|
+
export function copyFileSync(src: string, dest: string): void {
|
|
477
|
+
copyFileNative(src, dest);
|
|
478
|
+
}
|
|
479
|
+
|
|
480
|
+
export function accessSync(path: string, mode?: number): void {
|
|
481
|
+
accessNative(path, mode ?? constants.F_OK);
|
|
482
|
+
}
|
|
483
|
+
|
|
484
|
+
export function chmodSync(path: string, mode: number): void {
|
|
485
|
+
chmodNative(path, mode);
|
|
486
|
+
}
|
|
487
|
+
|
|
488
|
+
export function realpathSync(path: string): string {
|
|
489
|
+
return realpathNative(path);
|
|
490
|
+
}
|
|
491
|
+
|
|
492
|
+
export function mkdtempSync(prefix: string): string {
|
|
493
|
+
return mkdtempNative(prefix);
|
|
494
|
+
}
|
|
495
|
+
|
|
496
|
+
export function existsSync(path: string): boolean {
|
|
497
|
+
try {
|
|
498
|
+
accessSync(path, constants.F_OK);
|
|
499
|
+
return true;
|
|
500
|
+
} catch {
|
|
501
|
+
return false;
|
|
502
|
+
}
|
|
503
|
+
}
|
|
504
|
+
|
|
505
|
+
export function openSync(path: string, flags?: string | number, mode?: number): number {
|
|
506
|
+
return openFileDescriptor(path, flags, mode);
|
|
507
|
+
}
|
|
508
|
+
|
|
509
|
+
export function closeSync(fd: number): void {
|
|
510
|
+
closeFileDescriptor(fd);
|
|
511
|
+
}
|
|
512
|
+
|
|
513
|
+
export function readSync(fd: number, buffer: Uint8Array, offset = 0, length = buffer.byteLength - offset, position?: number | null): number {
|
|
514
|
+
const chunk = readFileDescriptor(fd, length, position);
|
|
515
|
+
buffer.set(chunk.subarray(0, chunk.byteLength), offset);
|
|
516
|
+
return chunk.byteLength;
|
|
517
|
+
}
|
|
518
|
+
|
|
519
|
+
export function writeSync(
|
|
520
|
+
fd: number,
|
|
521
|
+
buffer: FileData,
|
|
522
|
+
offsetOrPosition?: number,
|
|
523
|
+
lengthOrEncoding?: number | string,
|
|
524
|
+
position?: number | null,
|
|
525
|
+
): number {
|
|
526
|
+
if (typeof buffer === 'string') {
|
|
527
|
+
const encoded = toUint8Array(buffer);
|
|
528
|
+
const writePosition = typeof offsetOrPosition === 'number' ? offsetOrPosition : position;
|
|
529
|
+
return writeFileDescriptor(fd, encoded, writePosition);
|
|
530
|
+
}
|
|
531
|
+
|
|
532
|
+
const offset = typeof offsetOrPosition === 'number' ? offsetOrPosition : 0;
|
|
533
|
+
const length = typeof lengthOrEncoding === 'number' ? lengthOrEncoding : buffer.byteLength - offset;
|
|
534
|
+
const slice = buffer.subarray(offset, offset + length);
|
|
535
|
+
return writeFileDescriptor(fd, slice, position);
|
|
536
|
+
}
|
|
537
|
+
|
|
538
|
+
export function createReadStream(path: string, options?: ConstructorParameters<typeof ReadStream>[1]): ReadStream {
|
|
539
|
+
return new ReadStream(path, options);
|
|
540
|
+
}
|
|
541
|
+
|
|
542
|
+
export function createWriteStream(path: string, options?: ConstructorParameters<typeof WriteStream>[1]): WriteStream {
|
|
543
|
+
return new WriteStream(path, options);
|
|
544
|
+
}
|
|
545
|
+
|
|
546
|
+
export function readFile(
|
|
547
|
+
path: string,
|
|
548
|
+
optionsOrCallback: { encoding?: string } | string | Callback<Uint8Array | Buffer | string>,
|
|
549
|
+
callback?: Callback<Uint8Array | Buffer | string>,
|
|
550
|
+
): void {
|
|
551
|
+
let options: { encoding?: string } | string | undefined;
|
|
552
|
+
let cb: Callback<Uint8Array | Buffer | string>;
|
|
553
|
+
if (typeof optionsOrCallback === 'function') {
|
|
554
|
+
cb = optionsOrCallback;
|
|
555
|
+
} else {
|
|
556
|
+
options = optionsOrCallback;
|
|
557
|
+
cb = callback!;
|
|
558
|
+
}
|
|
559
|
+
wrapCallback(() => readFileSync(path, options), cb);
|
|
560
|
+
}
|
|
561
|
+
|
|
562
|
+
export function writeFile(
|
|
563
|
+
path: string,
|
|
564
|
+
data: FileData,
|
|
565
|
+
optionsOrCallback: { encoding?: string } | string | Callback,
|
|
566
|
+
callback?: Callback,
|
|
567
|
+
): void {
|
|
568
|
+
let options: { encoding?: string } | string | undefined;
|
|
569
|
+
let cb: Callback;
|
|
570
|
+
if (typeof optionsOrCallback === 'function') {
|
|
571
|
+
cb = optionsOrCallback;
|
|
572
|
+
} else {
|
|
573
|
+
options = optionsOrCallback;
|
|
574
|
+
cb = callback!;
|
|
575
|
+
}
|
|
576
|
+
wrapCallback(() => writeFileSync(path, data, options), cb);
|
|
577
|
+
}
|
|
578
|
+
|
|
579
|
+
export function appendFile(
|
|
580
|
+
path: string,
|
|
581
|
+
data: FileData,
|
|
582
|
+
optionsOrCallback: { encoding?: string } | string | Callback,
|
|
583
|
+
callback?: Callback,
|
|
584
|
+
): void {
|
|
585
|
+
let options: { encoding?: string } | string | undefined;
|
|
586
|
+
let cb: Callback;
|
|
587
|
+
if (typeof optionsOrCallback === 'function') {
|
|
588
|
+
cb = optionsOrCallback;
|
|
589
|
+
} else {
|
|
590
|
+
options = optionsOrCallback;
|
|
591
|
+
cb = callback!;
|
|
592
|
+
}
|
|
593
|
+
wrapCallback(() => appendFileSync(path, data, options), cb);
|
|
594
|
+
}
|
|
595
|
+
|
|
596
|
+
export function stat(path: string, callback: Callback<Stats>): void {
|
|
597
|
+
wrapCallback(() => statSync(path), callback);
|
|
598
|
+
}
|
|
599
|
+
|
|
600
|
+
export function lstat(path: string, callback: Callback<Stats>): void {
|
|
601
|
+
wrapCallback(() => lstatSync(path), callback);
|
|
602
|
+
}
|
|
603
|
+
|
|
604
|
+
export function readdir(
|
|
605
|
+
path: string,
|
|
606
|
+
optionsOrCallback: { withFileTypes?: boolean } | Callback<string[] | Dirent[]>,
|
|
607
|
+
callback?: Callback<string[] | Dirent[]>,
|
|
608
|
+
): void {
|
|
609
|
+
let options: { withFileTypes?: boolean } | undefined;
|
|
610
|
+
let cb: Callback<string[] | Dirent[]>;
|
|
611
|
+
if (typeof optionsOrCallback === 'function') {
|
|
612
|
+
cb = optionsOrCallback;
|
|
613
|
+
} else {
|
|
614
|
+
options = optionsOrCallback;
|
|
615
|
+
cb = callback!;
|
|
616
|
+
}
|
|
617
|
+
wrapCallback(() => readdirSync(path, options), cb);
|
|
618
|
+
}
|
|
619
|
+
|
|
620
|
+
export function mkdir(path: string, optionsOrCallback: { recursive?: boolean } | number | Callback, callback?: Callback): void {
|
|
621
|
+
let options: { recursive?: boolean } | number | undefined;
|
|
622
|
+
let cb: Callback;
|
|
623
|
+
if (typeof optionsOrCallback === 'function') {
|
|
624
|
+
cb = optionsOrCallback;
|
|
625
|
+
} else {
|
|
626
|
+
options = optionsOrCallback;
|
|
627
|
+
cb = callback!;
|
|
628
|
+
}
|
|
629
|
+
wrapCallback(() => mkdirSync(path, options), cb);
|
|
630
|
+
}
|
|
631
|
+
|
|
632
|
+
export function rmdir(path: string, callback: Callback): void {
|
|
633
|
+
wrapCallback(() => rmdirSync(path), callback);
|
|
634
|
+
}
|
|
635
|
+
|
|
636
|
+
export function unlink(path: string, callback: Callback): void {
|
|
637
|
+
wrapCallback(() => unlinkSync(path), callback);
|
|
638
|
+
}
|
|
639
|
+
|
|
640
|
+
export function rename(oldPath: string, newPath: string, callback: Callback): void {
|
|
641
|
+
wrapCallback(() => renameSync(oldPath, newPath), callback);
|
|
642
|
+
}
|
|
643
|
+
|
|
644
|
+
export function copyFile(src: string, dest: string, callback: Callback): void {
|
|
645
|
+
wrapCallback(() => copyFileSync(src, dest), callback);
|
|
646
|
+
}
|
|
647
|
+
|
|
648
|
+
export function access(path: string, modeOrCallback: number | Callback, callback?: Callback): void {
|
|
649
|
+
let mode: number | undefined;
|
|
650
|
+
let cb: Callback;
|
|
651
|
+
if (typeof modeOrCallback === 'function') {
|
|
652
|
+
cb = modeOrCallback;
|
|
653
|
+
} else {
|
|
654
|
+
mode = modeOrCallback;
|
|
655
|
+
cb = callback!;
|
|
656
|
+
}
|
|
657
|
+
wrapCallback(() => accessSync(path, mode), cb);
|
|
658
|
+
}
|
|
659
|
+
|
|
660
|
+
export function chmod(path: string, mode: number, callback: Callback): void {
|
|
661
|
+
wrapCallback(() => chmodSync(path, mode), callback);
|
|
662
|
+
}
|
|
663
|
+
|
|
664
|
+
export function realpath(path: string, callback: Callback<string>): void {
|
|
665
|
+
wrapCallback(() => realpathSync(path), callback);
|
|
666
|
+
}
|
|
667
|
+
|
|
668
|
+
export function mkdtemp(prefix: string, callback: Callback<string>): void {
|
|
669
|
+
wrapCallback(() => mkdtempSync(prefix), callback);
|
|
670
|
+
}
|
|
671
|
+
|
|
672
|
+
export function exists(path: string, callback: (exists: boolean) => void): void {
|
|
673
|
+
queueTask(() => callback(existsSync(path)));
|
|
674
|
+
}
|
|
675
|
+
|
|
676
|
+
export function open(
|
|
677
|
+
path: string,
|
|
678
|
+
flagsOrCallback?: string | number | Callback<number>,
|
|
679
|
+
modeOrCallback?: number | Callback<number>,
|
|
680
|
+
callback?: Callback<number>,
|
|
681
|
+
): void {
|
|
682
|
+
let flags: string | number | undefined;
|
|
683
|
+
let mode: number | undefined;
|
|
684
|
+
let cb: Callback<number>;
|
|
685
|
+
|
|
686
|
+
if (typeof flagsOrCallback === 'function') {
|
|
687
|
+
cb = flagsOrCallback;
|
|
688
|
+
} else if (typeof modeOrCallback === 'function') {
|
|
689
|
+
flags = flagsOrCallback;
|
|
690
|
+
cb = modeOrCallback;
|
|
691
|
+
} else {
|
|
692
|
+
flags = flagsOrCallback;
|
|
693
|
+
mode = modeOrCallback;
|
|
694
|
+
cb = callback!;
|
|
695
|
+
}
|
|
696
|
+
|
|
697
|
+
wrapCallback(() => openSync(path, flags, mode), cb);
|
|
698
|
+
}
|
|
699
|
+
|
|
700
|
+
export function close(fd: number, callback: Callback): void {
|
|
701
|
+
wrapCallback(() => closeSync(fd), callback);
|
|
702
|
+
}
|
|
703
|
+
|
|
704
|
+
export function read(
|
|
705
|
+
fd: number,
|
|
706
|
+
buffer: Uint8Array,
|
|
707
|
+
offset: number,
|
|
708
|
+
length: number,
|
|
709
|
+
position: number | null,
|
|
710
|
+
callback: ReadCallback,
|
|
711
|
+
): void {
|
|
712
|
+
queueTask(() => {
|
|
713
|
+
try {
|
|
714
|
+
const bytesRead = readSync(fd, buffer, offset, length, position);
|
|
715
|
+
callback(null, bytesRead, buffer);
|
|
716
|
+
} catch (error) {
|
|
717
|
+
callback(error instanceof Error ? error : new Error(String(error)), 0, buffer);
|
|
718
|
+
}
|
|
719
|
+
});
|
|
720
|
+
}
|
|
721
|
+
|
|
722
|
+
export function write(
|
|
723
|
+
fd: number,
|
|
724
|
+
buffer: string | Uint8Array,
|
|
725
|
+
offsetOrCallback: number | WriteCallback,
|
|
726
|
+
lengthOrCallback?: number | string | WriteCallback,
|
|
727
|
+
position?: number | null,
|
|
728
|
+
callback?: WriteCallback,
|
|
729
|
+
): void {
|
|
730
|
+
let offset = 0;
|
|
731
|
+
let lengthOrEncoding: number | string | undefined;
|
|
732
|
+
let cb: WriteCallback;
|
|
733
|
+
|
|
734
|
+
if (typeof offsetOrCallback === 'function') {
|
|
735
|
+
cb = offsetOrCallback;
|
|
736
|
+
} else if (typeof lengthOrCallback === 'function') {
|
|
737
|
+
offset = offsetOrCallback;
|
|
738
|
+
cb = lengthOrCallback;
|
|
739
|
+
} else {
|
|
740
|
+
offset = offsetOrCallback;
|
|
741
|
+
lengthOrEncoding = lengthOrCallback;
|
|
742
|
+
cb = callback!;
|
|
743
|
+
}
|
|
744
|
+
|
|
745
|
+
queueTask(() => {
|
|
746
|
+
try {
|
|
747
|
+
const bytesWritten = writeSync(fd, buffer, offset, lengthOrEncoding, position);
|
|
748
|
+
cb(null, bytesWritten, buffer);
|
|
749
|
+
} catch (error) {
|
|
750
|
+
cb(error instanceof Error ? error : new Error(String(error)), 0, buffer);
|
|
751
|
+
}
|
|
752
|
+
});
|
|
753
|
+
}
|
|
754
|
+
|
|
755
|
+
// --- symlink ---
|
|
756
|
+
|
|
757
|
+
export function symlinkSync(target: string, path: string, type?: string): void {
|
|
758
|
+
const targetPath = toPathString(target, 'target');
|
|
759
|
+
const linkPath = toPathString(path, 'path');
|
|
760
|
+
validateSymlinkType(type);
|
|
761
|
+
symlinkNative(targetPath, linkPath);
|
|
762
|
+
}
|
|
763
|
+
|
|
764
|
+
export function symlink(target: string, path: string, typeOrCallback: string | Callback, callback?: Callback): void {
|
|
765
|
+
const type = typeof typeOrCallback === 'function' ? undefined : typeOrCallback;
|
|
766
|
+
toPathString(target, 'target');
|
|
767
|
+
toPathString(path, 'path');
|
|
768
|
+
validateSymlinkType(type);
|
|
769
|
+
const cb = typeof typeOrCallback === 'function' ? typeOrCallback : callback!;
|
|
770
|
+
wrapCallback(() => symlinkSync(target, path, type), cb);
|
|
771
|
+
}
|
|
772
|
+
|
|
773
|
+
// --- readlink ---
|
|
774
|
+
|
|
775
|
+
export function readlinkSync(path: string): string {
|
|
776
|
+
return readlinkNative(path);
|
|
777
|
+
}
|
|
778
|
+
|
|
779
|
+
export function readlink(path: string, callback: Callback<string>): void {
|
|
780
|
+
wrapCallback(() => readlinkSync(path), callback);
|
|
781
|
+
}
|
|
782
|
+
|
|
783
|
+
// --- link ---
|
|
784
|
+
|
|
785
|
+
export function linkSync(existingPath: string, newPath: string): void {
|
|
786
|
+
linkNative(existingPath, newPath);
|
|
787
|
+
}
|
|
788
|
+
|
|
789
|
+
export function link(existingPath: string, newPath: string, callback: Callback): void {
|
|
790
|
+
wrapCallback(() => linkSync(existingPath, newPath), callback);
|
|
791
|
+
}
|
|
792
|
+
|
|
793
|
+
// --- truncate ---
|
|
794
|
+
|
|
795
|
+
export function truncateSync(path: string, len = 0): void {
|
|
796
|
+
truncateNative(path, len);
|
|
797
|
+
}
|
|
798
|
+
|
|
799
|
+
export function truncate(path: string, lenOrCallback: number | Callback, callback?: Callback): void {
|
|
800
|
+
let len: number;
|
|
801
|
+
let cb: Callback;
|
|
802
|
+
if (typeof lenOrCallback === 'function') {
|
|
803
|
+
len = 0;
|
|
804
|
+
cb = lenOrCallback;
|
|
805
|
+
} else {
|
|
806
|
+
len = lenOrCallback;
|
|
807
|
+
cb = callback!;
|
|
808
|
+
}
|
|
809
|
+
wrapCallback(() => truncateSync(path, len), cb);
|
|
810
|
+
}
|
|
811
|
+
|
|
812
|
+
// --- ftruncate ---
|
|
813
|
+
|
|
814
|
+
export function ftruncateSync(fd: number, len = 0): void {
|
|
815
|
+
// Write empty data at position to truncate via fd
|
|
816
|
+
// Fall back to no-op if not available at fd level
|
|
817
|
+
truncateNative(`/proc/self/fd/${fd}`, len);
|
|
818
|
+
}
|
|
819
|
+
|
|
820
|
+
export function ftruncate(fd: number, lenOrCallback: number | Callback, callback?: Callback): void {
|
|
821
|
+
let len: number;
|
|
822
|
+
let cb: Callback;
|
|
823
|
+
if (typeof lenOrCallback === 'function') {
|
|
824
|
+
len = 0;
|
|
825
|
+
cb = lenOrCallback;
|
|
826
|
+
} else {
|
|
827
|
+
len = lenOrCallback;
|
|
828
|
+
cb = callback!;
|
|
829
|
+
}
|
|
830
|
+
wrapCallback(() => ftruncateSync(fd, len), cb);
|
|
831
|
+
}
|
|
832
|
+
|
|
833
|
+
// --- utimes ---
|
|
834
|
+
|
|
835
|
+
export function utimesSync(path: string, atime: number | Date, mtime: number | Date): void {
|
|
836
|
+
const targetPath = toPathString(path, 'path');
|
|
837
|
+
utimesNative(targetPath, normalizeUtimesValue(atime), normalizeUtimesValue(mtime));
|
|
838
|
+
}
|
|
839
|
+
|
|
840
|
+
export function utimes(path: string, atime: number | Date, mtime: number | Date, callback: Callback): void {
|
|
841
|
+
toPathString(path, 'path');
|
|
842
|
+
wrapCallback(() => utimesSync(path, atime, mtime), callback);
|
|
843
|
+
}
|
|
844
|
+
|
|
845
|
+
// --- rm ---
|
|
846
|
+
|
|
847
|
+
export function rmSync(path: string, options?: { recursive?: boolean; force?: boolean }): void {
|
|
848
|
+
const targetPath = toPathString(path, 'path');
|
|
849
|
+
const recursive = options?.recursive === true;
|
|
850
|
+
const force = options?.force === true;
|
|
851
|
+
|
|
852
|
+
try {
|
|
853
|
+
const info = lstatSync(targetPath);
|
|
854
|
+
if (info.isDirectory()) {
|
|
855
|
+
if (recursive) {
|
|
856
|
+
const entries = readdirSync(targetPath) as string[];
|
|
857
|
+
for (const entry of entries) {
|
|
858
|
+
rmSync(join(targetPath, entry), options);
|
|
859
|
+
}
|
|
860
|
+
}
|
|
861
|
+
try {
|
|
862
|
+
rmdirSync(targetPath);
|
|
863
|
+
} catch (error) {
|
|
864
|
+
throw normalizeRmError(error, targetPath, recursive);
|
|
865
|
+
}
|
|
866
|
+
} else {
|
|
867
|
+
try {
|
|
868
|
+
unlinkSync(targetPath);
|
|
869
|
+
} catch (error) {
|
|
870
|
+
throw normalizeRmError(error, targetPath, recursive);
|
|
871
|
+
}
|
|
872
|
+
}
|
|
873
|
+
} catch (error) {
|
|
874
|
+
const normalizedError = normalizeRmError(error, targetPath, recursive);
|
|
875
|
+
if (
|
|
876
|
+
force &&
|
|
877
|
+
normalizedError &&
|
|
878
|
+
typeof normalizedError === 'object' &&
|
|
879
|
+
(normalizedError as { code?: string }).code === 'ENOENT'
|
|
880
|
+
) {
|
|
881
|
+
return;
|
|
882
|
+
}
|
|
883
|
+
throw normalizedError;
|
|
884
|
+
}
|
|
885
|
+
}
|
|
886
|
+
|
|
887
|
+
export function rm(path: string, optionsOrCallback: { recursive?: boolean; force?: boolean } | Callback, callback?: Callback): void {
|
|
888
|
+
let options: { recursive?: boolean; force?: boolean } | undefined;
|
|
889
|
+
let cb: Callback;
|
|
890
|
+
if (typeof optionsOrCallback === 'function') {
|
|
891
|
+
cb = optionsOrCallback;
|
|
892
|
+
} else {
|
|
893
|
+
options = optionsOrCallback;
|
|
894
|
+
cb = callback!;
|
|
895
|
+
}
|
|
896
|
+
toPathString(path, 'path');
|
|
897
|
+
wrapCallback(() => rmSync(path, options), cb);
|
|
898
|
+
}
|
|
899
|
+
|
|
900
|
+
// --- fstat ---
|
|
901
|
+
|
|
902
|
+
export function fstatSync(fd: number): Stats {
|
|
903
|
+
// Read stat via fd path
|
|
904
|
+
return statSync(`/proc/self/fd/${fd}`);
|
|
905
|
+
}
|
|
906
|
+
|
|
907
|
+
export function fstat(fd: number, callback: Callback<Stats>): void {
|
|
908
|
+
wrapCallback(() => fstatSync(fd), callback);
|
|
909
|
+
}
|
|
910
|
+
|
|
911
|
+
// --- fchmod ---
|
|
912
|
+
|
|
913
|
+
export function fchmodSync(fd: number, mode: number): void {
|
|
914
|
+
chmodSync(`/proc/self/fd/${fd}`, mode);
|
|
915
|
+
}
|
|
916
|
+
|
|
917
|
+
export function fchmod(fd: number, mode: number, callback: Callback): void {
|
|
918
|
+
wrapCallback(() => fchmodSync(fd, mode), callback);
|
|
919
|
+
}
|
|
920
|
+
|
|
921
|
+
// --- watch stubs ---
|
|
922
|
+
|
|
923
|
+
export function watch(_filename: string, _options?: any, _listener?: any): any {
|
|
924
|
+
const watcher: any = {
|
|
925
|
+
close() {},
|
|
926
|
+
on() { return watcher; },
|
|
927
|
+
once() { return watcher; },
|
|
928
|
+
addListener() { return watcher; },
|
|
929
|
+
removeListener() { return watcher; },
|
|
930
|
+
off() { return watcher; },
|
|
931
|
+
emit() { return false; },
|
|
932
|
+
ref() { return watcher; },
|
|
933
|
+
unref() { return watcher; },
|
|
934
|
+
};
|
|
935
|
+
return watcher;
|
|
936
|
+
}
|
|
937
|
+
|
|
938
|
+
export function watchFile(_filename: string, _options?: any, _listener?: any): any {
|
|
939
|
+
return watch(_filename);
|
|
940
|
+
}
|
|
941
|
+
|
|
942
|
+
export function unwatchFile(_filename: string, _listener?: any): void {
|
|
943
|
+
// no-op
|
|
944
|
+
}
|