@serveryyswys/node.operit 0.0.0-stage → 0.1.2

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.
Files changed (123) hide show
  1. package/BUILTINS.json +233 -0
  2. package/DESIGN.md +513 -0
  3. package/LICENSE +674 -0
  4. package/README.md +301 -2
  5. package/dist/assert/strict.d.ts +2 -0
  6. package/dist/assert/strict.js +7 -0
  7. package/dist/assert.d.ts +3 -0
  8. package/dist/assert.js +483 -0
  9. package/dist/buffer.d.ts +60 -0
  10. package/dist/buffer.js +524 -0
  11. package/dist/child_process.d.ts +56 -0
  12. package/dist/child_process.js +371 -0
  13. package/dist/constants.d.ts +2 -0
  14. package/dist/constants.js +19 -0
  15. package/dist/crypto.d.ts +76 -0
  16. package/dist/crypto.js +312 -0
  17. package/dist/dns/promises.d.ts +34 -0
  18. package/dist/dns/promises.js +190 -0
  19. package/dist/dns.d.ts +88 -0
  20. package/dist/dns.js +259 -0
  21. package/dist/events.d.ts +40 -0
  22. package/dist/events.js +237 -0
  23. package/dist/fs/promises.d.ts +159 -0
  24. package/dist/fs/promises.js +129 -0
  25. package/dist/fs.d.ts +221 -0
  26. package/dist/fs.js +944 -0
  27. package/dist/http.d.ts +92 -0
  28. package/dist/http.js +319 -0
  29. package/dist/https.d.ts +296 -0
  30. package/dist/https.js +50 -0
  31. package/dist/index.d.ts +2422 -0
  32. package/dist/index.js +57 -0
  33. package/dist/lib/bridge.d.ts +60 -0
  34. package/dist/lib/bridge.js +205 -0
  35. package/dist/lib/bytes.d.ts +20 -0
  36. package/dist/lib/bytes.js +239 -0
  37. package/dist/lib/child-process-types.d.ts +45 -0
  38. package/dist/lib/child-process-types.js +2 -0
  39. package/dist/lib/cwd.d.ts +2 -0
  40. package/dist/lib/cwd.js +32 -0
  41. package/dist/lib/deep-equal.d.ts +3 -0
  42. package/dist/lib/deep-equal.js +223 -0
  43. package/dist/lib/deflate.d.ts +2 -0
  44. package/dist/lib/deflate.js +234 -0
  45. package/dist/lib/dns-driver.d.ts +14 -0
  46. package/dist/lib/dns-driver.js +85 -0
  47. package/dist/lib/dns-types.d.ts +22 -0
  48. package/dist/lib/dns-types.js +2 -0
  49. package/dist/lib/errors.d.ts +48 -0
  50. package/dist/lib/errors.js +424 -0
  51. package/dist/lib/fs-driver.d.ts +70 -0
  52. package/dist/lib/fs-driver.js +364 -0
  53. package/dist/lib/fs-env.d.ts +30 -0
  54. package/dist/lib/fs-env.js +157 -0
  55. package/dist/lib/fs-types.d.ts +19 -0
  56. package/dist/lib/fs-types.js +2 -0
  57. package/dist/lib/hashes.d.ts +27 -0
  58. package/dist/lib/hashes.js +432 -0
  59. package/dist/lib/http-driver.d.ts +30 -0
  60. package/dist/lib/http-driver.js +72 -0
  61. package/dist/lib/http-types.d.ts +18 -0
  62. package/dist/lib/http-types.js +2 -0
  63. package/dist/lib/inflate.d.ts +6 -0
  64. package/dist/lib/inflate.js +284 -0
  65. package/dist/lib/path-types.d.ts +37 -0
  66. package/dist/lib/path-types.js +2 -0
  67. package/dist/lib/paths.d.ts +8 -0
  68. package/dist/lib/paths.js +106 -0
  69. package/dist/lib/perf-hooks-types.d.ts +18 -0
  70. package/dist/lib/perf-hooks-types.js +2 -0
  71. package/dist/lib/process-driver.d.ts +31 -0
  72. package/dist/lib/process-driver.js +102 -0
  73. package/dist/lib/punycode.d.ts +8 -0
  74. package/dist/lib/punycode.js +179 -0
  75. package/dist/lib/stream-types.d.ts +29 -0
  76. package/dist/lib/stream-types.js +2 -0
  77. package/dist/lib/timers-types.d.ts +18 -0
  78. package/dist/lib/timers-types.js +2 -0
  79. package/dist/lib/url-search-params.d.ts +26 -0
  80. package/dist/lib/url-search-params.js +281 -0
  81. package/dist/lib/url-types.d.ts +44 -0
  82. package/dist/lib/url-types.js +2 -0
  83. package/dist/lib/url-whatwg.d.ts +78 -0
  84. package/dist/lib/url-whatwg.js +857 -0
  85. package/dist/lib/zlib-types.d.ts +12 -0
  86. package/dist/lib/zlib-types.js +2 -0
  87. package/dist/module.d.ts +8 -0
  88. package/dist/module.js +72 -0
  89. package/dist/os.d.ts +80 -0
  90. package/dist/os.js +247 -0
  91. package/dist/path/posix.d.ts +2 -0
  92. package/dist/path/posix.js +7 -0
  93. package/dist/path/win32.d.ts +2 -0
  94. package/dist/path/win32.js +10 -0
  95. package/dist/path.d.ts +3 -0
  96. package/dist/path.js +1222 -0
  97. package/dist/perf_hooks.d.ts +36 -0
  98. package/dist/perf_hooks.js +144 -0
  99. package/dist/process.d.ts +69 -0
  100. package/dist/process.js +230 -0
  101. package/dist/querystring.d.ts +15 -0
  102. package/dist/querystring.js +209 -0
  103. package/dist/stream/promises.d.ts +5 -0
  104. package/dist/stream/promises.js +10 -0
  105. package/dist/stream.d.ts +84 -0
  106. package/dist/stream.js +875 -0
  107. package/dist/string_decoder.d.ts +15 -0
  108. package/dist/string_decoder.js +237 -0
  109. package/dist/timers/promises.d.ts +19 -0
  110. package/dist/timers/promises.js +74 -0
  111. package/dist/timers.d.ts +21 -0
  112. package/dist/timers.js +41 -0
  113. package/dist/tty.d.ts +9 -0
  114. package/dist/tty.js +25 -0
  115. package/dist/unsupported.d.ts +12 -0
  116. package/dist/unsupported.js +17 -0
  117. package/dist/url.d.ts +28 -0
  118. package/dist/url.js +486 -0
  119. package/dist/util.d.ts +74 -0
  120. package/dist/util.js +515 -0
  121. package/dist/zlib.d.ts +88 -0
  122. package/dist/zlib.js +371 -0
  123. package/package.json +29 -4
package/dist/fs.js ADDED
@@ -0,0 +1,944 @@
1
+ 'use strict';
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
15
+ }) : function(o, v) {
16
+ o["default"] = v;
17
+ });
18
+ var __importStar = (this && this.__importStar) || (function () {
19
+ var ownKeys = function(o) {
20
+ ownKeys = Object.getOwnPropertyNames || function (o) {
21
+ var ar = [];
22
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
23
+ return ar;
24
+ };
25
+ return ownKeys(o);
26
+ };
27
+ return function (mod) {
28
+ if (mod && mod.__esModule) return mod;
29
+ var result = {};
30
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
31
+ __setModuleDefault(result, mod);
32
+ return result;
33
+ };
34
+ })();
35
+ /**
36
+ * Node fs 模块的移植(同步面)。
37
+ *
38
+ * 分层:本文件只做 Node 语义 —— 选项解析、flag 语义、错误码与返回值形状;
39
+ * 所有 I/O 走 lib/fs-driver,宿主假设收敛在那里。
40
+ *
41
+ * 环境状态机(lib/fs-env)在这里接入:环境决定 cwd,
42
+ * 于是相对路径的解析基准随环境改变,这就是"设置作用环境"的全部含义。
43
+ *
44
+ * 尚未实现:fd 系列(open/read/write/close)与流式 API,见 BUILTINS.json 的说明。
45
+ */
46
+ const pathModule = require("./path");
47
+ const env = __importStar(require("./lib/fs-env"));
48
+ const cwd = __importStar(require("./lib/cwd"));
49
+ const drivers = __importStar(require("./lib/fs-driver"));
50
+ const errors_1 = require("./lib/errors");
51
+ const buffer_1 = require("./buffer");
52
+ const streamModule = require("./stream");
53
+ // ------------------------------------------------------------------ 环境接入
54
+ env.setHooks({
55
+ setCwd: function (value) {
56
+ cwd.set(value);
57
+ },
58
+ getCwd: function () {
59
+ return cwd.get();
60
+ },
61
+ probe: function (root) {
62
+ const current = drivers.getDriver();
63
+ if (!current.exists(root)) {
64
+ throw (0, errors_1.createError)('ENOENT', 'stat', root);
65
+ }
66
+ }
67
+ });
68
+ function ready() {
69
+ env.ensureBound();
70
+ return drivers.getDriver();
71
+ }
72
+ function wrapCall(syscall, target, body, dest) {
73
+ try {
74
+ return body();
75
+ }
76
+ catch (failure) {
77
+ throw (0, errors_1.withContext)(failure, syscall, target, dest);
78
+ }
79
+ }
80
+ function toAbsolute(value, argumentName) {
81
+ if (typeof value !== 'string') {
82
+ throw new TypeError('The "' + argumentName + '" argument must be of type string. Received type ' + typeof value);
83
+ }
84
+ return pathModule.resolve(value);
85
+ }
86
+ // ------------------------------------------------------------------ 类型
87
+ const FILE_TYPE = 1;
88
+ const DIRECTORY_TYPE = 2;
89
+ const SYMLINK_TYPE = 3;
90
+ class Stats {
91
+ constructor(raw) {
92
+ this.sizeValue = raw.size;
93
+ this.modeValue = raw.mode;
94
+ this.atimeMsValue = raw.atimeMs;
95
+ this.mtimeMsValue = raw.mtimeMs;
96
+ this.ctimeMsValue = raw.ctimeMs;
97
+ this.birthtimeMsValue = raw.birthtimeMs;
98
+ this.fileLike = raw.isFile;
99
+ this.directoryLike = raw.isDirectory;
100
+ this.linkLike = raw.isSymbolicLink;
101
+ }
102
+ get size() {
103
+ return this.sizeValue;
104
+ }
105
+ get mode() {
106
+ return this.modeValue;
107
+ }
108
+ get atimeMs() {
109
+ return this.atimeMsValue;
110
+ }
111
+ get mtimeMs() {
112
+ return this.mtimeMsValue;
113
+ }
114
+ get ctimeMs() {
115
+ return this.ctimeMsValue;
116
+ }
117
+ get birthtimeMs() {
118
+ return this.birthtimeMsValue;
119
+ }
120
+ get atime() {
121
+ return new Date(this.atimeMsValue);
122
+ }
123
+ get mtime() {
124
+ return new Date(this.mtimeMsValue);
125
+ }
126
+ get ctime() {
127
+ return new Date(this.ctimeMsValue);
128
+ }
129
+ get birthtime() {
130
+ return new Date(this.birthtimeMsValue);
131
+ }
132
+ isFile() {
133
+ return this.fileLike;
134
+ }
135
+ isDirectory() {
136
+ return this.directoryLike;
137
+ }
138
+ isSymbolicLink() {
139
+ return this.linkLike;
140
+ }
141
+ isBlockDevice() {
142
+ return false;
143
+ }
144
+ isCharacterDevice() {
145
+ return false;
146
+ }
147
+ isFIFO() {
148
+ return false;
149
+ }
150
+ isSocket() {
151
+ return false;
152
+ }
153
+ }
154
+ class Dirent {
155
+ constructor(entry) {
156
+ this.name = entry.name;
157
+ this.kind = entry.isDirectory ? DIRECTORY_TYPE : (entry.isSymbolicLink ? SYMLINK_TYPE : FILE_TYPE);
158
+ }
159
+ isFile() {
160
+ return this.kind === FILE_TYPE;
161
+ }
162
+ isDirectory() {
163
+ return this.kind === DIRECTORY_TYPE;
164
+ }
165
+ isSymbolicLink() {
166
+ return this.kind === SYMLINK_TYPE;
167
+ }
168
+ isBlockDevice() {
169
+ return false;
170
+ }
171
+ isCharacterDevice() {
172
+ return false;
173
+ }
174
+ isFIFO() {
175
+ return false;
176
+ }
177
+ isSocket() {
178
+ return false;
179
+ }
180
+ }
181
+ const FLAGS = {
182
+ 'r': { readable: true, writable: false, append: false, exclusive: false, truncate: false, mustExist: true },
183
+ 'r+': { readable: true, writable: true, append: false, exclusive: false, truncate: false, mustExist: true },
184
+ 'w': { readable: false, writable: true, append: false, exclusive: false, truncate: true, mustExist: false },
185
+ 'w+': { readable: true, writable: true, append: false, exclusive: false, truncate: true, mustExist: false },
186
+ 'a': { readable: false, writable: true, append: true, exclusive: false, truncate: false, mustExist: false },
187
+ 'a+': { readable: true, writable: true, append: true, exclusive: false, truncate: false, mustExist: false },
188
+ 'wx': { readable: false, writable: true, append: false, exclusive: true, truncate: true, mustExist: false },
189
+ 'wx+': { readable: true, writable: true, append: false, exclusive: true, truncate: true, mustExist: false },
190
+ 'ax': { readable: false, writable: true, append: true, exclusive: true, truncate: false, mustExist: false },
191
+ 'ax+': { readable: true, writable: true, append: true, exclusive: true, truncate: false, mustExist: false }
192
+ };
193
+ function parseFlag(value) {
194
+ const text = value === undefined || value === null ? 'r' : String(value);
195
+ const spec = FLAGS[text];
196
+ if (spec === undefined) {
197
+ throw new TypeError('Unknown file open flag: ' + text);
198
+ }
199
+ return spec;
200
+ }
201
+ function normalizeEncoding(value) {
202
+ if (value === null || value === undefined) {
203
+ return null;
204
+ }
205
+ if (typeof value === 'string') {
206
+ return value;
207
+ }
208
+ if (typeof value === 'object' && typeof value.encoding === 'string') {
209
+ return value.encoding;
210
+ }
211
+ return null;
212
+ }
213
+ // ------------------------------------------------------------------ 同步 API
214
+ /** readFileSync / writeFileSync 也接受 fd(Node 支持),这里转成对应句柄。 */
215
+ function entryForDescriptor(descriptor, syscall) {
216
+ return resolveEntry(descriptor, syscall);
217
+ }
218
+ function readFileSync(target, options) {
219
+ if (typeof target === 'number') {
220
+ const entry = entryForDescriptor(target, 'read');
221
+ const size = entry.handle.size();
222
+ const data = entry.handle.read(0, size);
223
+ const buffer = buffer_1.Buffer.from(data);
224
+ const encoding = normalizeEncoding(options);
225
+ return encoding === null ? buffer : buffer.toString(encoding);
226
+ }
227
+ const file = toAbsolute(target, 'path');
228
+ const encoding = normalizeEncoding(options);
229
+ const flag = options !== null && typeof options === 'object'
230
+ ? options.flag
231
+ : undefined;
232
+ const spec = parseFlag(flag);
233
+ if (!spec.readable) {
234
+ throw (0, errors_1.createError)('EBADF', 'read', file);
235
+ }
236
+ const current = ready();
237
+ const data = wrapCall('open', file, function () {
238
+ return current.readFileBytes(file);
239
+ });
240
+ const buffer = buffer_1.Buffer.from(data);
241
+ return encoding === null ? buffer : buffer.toString(encoding);
242
+ }
243
+ function writeFileSync(target, data, options) {
244
+ if (typeof target === 'number') {
245
+ const entry = entryForDescriptor(target, 'write');
246
+ const encoding = normalizeEncoding(options);
247
+ const payload = toBytes(data, encoding === null ? 'utf8' : encoding);
248
+ entry.handle.truncate(0);
249
+ entry.handle.write(0, payload);
250
+ return;
251
+ }
252
+ const file = toAbsolute(target, 'path');
253
+ // writeFileSync 的默认 flag 是 'w'(readFileSync 才是 'r')
254
+ const declaredFlag = options !== null && typeof options === 'object'
255
+ ? options.flag
256
+ : undefined;
257
+ const spec = parseFlag(declaredFlag === undefined ? 'w' : declaredFlag);
258
+ if (!spec.writable) {
259
+ throw (0, errors_1.createError)('EBADF', 'write', file);
260
+ }
261
+ const encoding = normalizeEncoding(options);
262
+ const payload = toBytes(data, encoding === null ? 'utf8' : encoding);
263
+ const current = ready();
264
+ wrapCall('open', file, function () {
265
+ if (spec.mustExist && !current.exists(file)) {
266
+ throw (0, errors_1.createError)('ENOENT', 'open', file);
267
+ }
268
+ if (spec.truncate || spec.append) {
269
+ current.writeFileBytes(file, payload, spec.append, spec.exclusive);
270
+ return;
271
+ }
272
+ // r+ :从 0 覆盖,保留尾部
273
+ const existing = current.exists(file) ? current.readFileBytes(file) : new Uint8Array(0);
274
+ const merged = new Uint8Array(Math.max(existing.length, payload.length));
275
+ merged.set(existing);
276
+ merged.set(payload, 0);
277
+ current.writeFileBytes(file, merged, false, false);
278
+ });
279
+ }
280
+ function appendFileSync(target, data, options) {
281
+ const encoding = normalizeEncoding(options);
282
+ const payload = toBytes(data, encoding === null ? 'utf8' : encoding);
283
+ const file = toAbsolute(target, 'path');
284
+ const current = ready();
285
+ wrapCall('open', file, function () {
286
+ current.writeFileBytes(file, payload, true, false);
287
+ });
288
+ }
289
+ function toBytes(data, encoding) {
290
+ if (typeof data === 'string') {
291
+ return buffer_1.Buffer.from(data, encoding);
292
+ }
293
+ if (data instanceof Uint8Array) {
294
+ return data;
295
+ }
296
+ if (data instanceof ArrayBuffer) {
297
+ return new Uint8Array(data);
298
+ }
299
+ throw new TypeError('The "data" argument must be of type string or an instance of Buffer, TypedArray, or DataView.');
300
+ }
301
+ function existsSync(target) {
302
+ if (typeof target !== 'string') {
303
+ return false;
304
+ }
305
+ try {
306
+ env.ensureBound();
307
+ return drivers.getDriver().exists(pathModule.resolve(target));
308
+ }
309
+ catch (failure) {
310
+ return false;
311
+ }
312
+ }
313
+ function statSync(target, options) {
314
+ const file = toAbsolute(target, 'path');
315
+ const throwIfNoEntry = options !== null && typeof options === 'object' &&
316
+ options.throwIfNoEntry === false
317
+ ? false
318
+ : true;
319
+ const bigint = options !== null && typeof options === 'object' &&
320
+ options.bigint === true;
321
+ if (bigint) {
322
+ throw (0, errors_1.onjError)('ONJ_UNSUPPORTED', 'bigint 形式的 Stats 尚未实现。');
323
+ }
324
+ const current = ready();
325
+ try {
326
+ return new Stats(current.stat(file, true));
327
+ }
328
+ catch (failure) {
329
+ if (!throwIfNoEntry && isMissing(failure)) {
330
+ return undefined;
331
+ }
332
+ throw (0, errors_1.withContext)(failure, 'stat', file);
333
+ }
334
+ }
335
+ function lstatSync(target, options) {
336
+ const file = toAbsolute(target, 'path');
337
+ const throwIfNoEntry = options !== null && typeof options === 'object' &&
338
+ options.throwIfNoEntry === false
339
+ ? false
340
+ : true;
341
+ const current = ready();
342
+ try {
343
+ return new Stats(current.stat(file, false));
344
+ }
345
+ catch (failure) {
346
+ if (!throwIfNoEntry && isMissing(failure)) {
347
+ return undefined;
348
+ }
349
+ throw (0, errors_1.withContext)(failure, 'lstat', file);
350
+ }
351
+ }
352
+ function isMissing(failure) {
353
+ return failure?.code === 'ENOENT';
354
+ }
355
+ function readdirSync(target, options) {
356
+ const dir = toAbsolute(target, 'path');
357
+ const withFileTypes = options !== null && typeof options === 'object' &&
358
+ options.withFileTypes === true;
359
+ const current = ready();
360
+ const entries = wrapCall('scandir', dir, function () {
361
+ return current.readdir(dir);
362
+ });
363
+ if (withFileTypes) {
364
+ return entries.map(function (entry) {
365
+ return new Dirent(entry);
366
+ });
367
+ }
368
+ return entries.map(function (entry) {
369
+ return entry.name;
370
+ });
371
+ }
372
+ function mkdirSync(target, options) {
373
+ const dir = toAbsolute(target, 'path');
374
+ const recursive = options !== null && typeof options === 'object' &&
375
+ options.recursive === true;
376
+ const current = ready();
377
+ return wrapCall('mkdir', dir, function () {
378
+ return current.mkdir(dir, recursive);
379
+ });
380
+ }
381
+ function rmSync(target, options) {
382
+ const file = toAbsolute(target, 'path');
383
+ const recursive = options !== null && typeof options === 'object' &&
384
+ options.recursive === true;
385
+ const force = options !== null && typeof options === 'object' &&
386
+ options.force === true;
387
+ const current = ready();
388
+ wrapCall('rm', file, function () {
389
+ current.remove(file, recursive, force);
390
+ });
391
+ }
392
+ function unlinkSync(target) {
393
+ const file = toAbsolute(target, 'path');
394
+ const current = ready();
395
+ wrapCall('unlink', file, function () {
396
+ current.remove(file, false, false);
397
+ });
398
+ }
399
+ function rmdirSync(target, options) {
400
+ const dir = toAbsolute(target, 'path');
401
+ const recursive = options !== null && typeof options === 'object' &&
402
+ options.recursive === true;
403
+ const current = ready();
404
+ wrapCall('rmdir', dir, function () {
405
+ current.remove(dir, recursive, false);
406
+ });
407
+ }
408
+ function renameSync(from, to) {
409
+ const source = toAbsolute(from, 'oldPath');
410
+ const destination = toAbsolute(to, 'newPath');
411
+ const current = ready();
412
+ wrapCall('rename', source, function () {
413
+ current.rename(source, destination);
414
+ }, destination);
415
+ }
416
+ function copyFileSync(from, to) {
417
+ const source = toAbsolute(from, 'src');
418
+ const destination = toAbsolute(to, 'dest');
419
+ const current = ready();
420
+ wrapCall('copyfile', source, function () {
421
+ current.copyFile(source, destination);
422
+ }, destination);
423
+ }
424
+ function realpathSync(target) {
425
+ const file = toAbsolute(target, 'path');
426
+ const current = ready();
427
+ return wrapCall('realpath', file, function () {
428
+ return current.realpath(file);
429
+ });
430
+ }
431
+ function readlinkSync(target) {
432
+ const file = toAbsolute(target, 'path');
433
+ const current = ready();
434
+ return wrapCall('readlink', file, function () {
435
+ return current.readlink(file);
436
+ });
437
+ }
438
+ function symlinkSync(target, linkPath) {
439
+ const linkTarget = String(target);
440
+ const file = toAbsolute(linkPath, 'path');
441
+ const current = ready();
442
+ wrapCall('symlink', file, function () {
443
+ current.symlink(linkTarget, file);
444
+ });
445
+ }
446
+ function chmodSync(target, mode) {
447
+ const file = toAbsolute(target, 'path');
448
+ const current = ready();
449
+ wrapCall('chmod', file, function () {
450
+ current.chmod(file, Number(mode) || 0);
451
+ });
452
+ }
453
+ function truncateSync(target, length) {
454
+ const file = toAbsolute(target, 'path');
455
+ const size = length === undefined ? 0 : Number(length);
456
+ const current = ready();
457
+ wrapCall('truncate', file, function () {
458
+ current.truncate(file, size);
459
+ });
460
+ }
461
+ function utimesSync(target, atime, mtime) {
462
+ const file = toAbsolute(target, 'path');
463
+ const current = ready();
464
+ wrapCall('utime', file, function () {
465
+ current.utimes(file, toMillis(atime), toMillis(mtime));
466
+ });
467
+ }
468
+ function toMillis(value) {
469
+ if (value instanceof Date) {
470
+ return value.getTime();
471
+ }
472
+ if (typeof value === 'number') {
473
+ return value * 1000;
474
+ }
475
+ return Number(value) * 1000;
476
+ }
477
+ function accessSync(target) {
478
+ const file = toAbsolute(target, 'path');
479
+ const current = ready();
480
+ wrapCall('access', file, function () {
481
+ if (!current.exists(file)) {
482
+ throw (0, errors_1.createError)('ENOENT', 'access', file);
483
+ }
484
+ });
485
+ }
486
+ function mkdtempSync(prefix) {
487
+ const base = toAbsolute(prefix, 'prefix');
488
+ const current = ready();
489
+ return wrapCall('mkdtemp', base, function () {
490
+ return current.mkdtemp(base);
491
+ });
492
+ }
493
+ /** Node 的 fd 是小整数;0/1/2 留给 stdio,所以从 3 开始发。 */
494
+ const openEntries = new Map();
495
+ let nextDescriptor = 3;
496
+ function resolveEntry(descriptor, syscall) {
497
+ const value = Number(descriptor);
498
+ const entry = openEntries.get(value);
499
+ if (entry === undefined) {
500
+ throw (0, errors_1.createError)('EBADF', syscall, String(descriptor));
501
+ }
502
+ return entry;
503
+ }
504
+ function openSync(target, flags, mode) {
505
+ void mode;
506
+ const file = toAbsolute(target, 'path');
507
+ const spec = parseFlag(flags);
508
+ const current = ready();
509
+ const options = {
510
+ readable: spec.readable,
511
+ writable: spec.writable,
512
+ append: spec.append,
513
+ exclusive: spec.exclusive,
514
+ truncate: spec.truncate
515
+ };
516
+ const handle = wrapCall('open', file, function () {
517
+ return current.openHandle(file, options);
518
+ });
519
+ const descriptor = nextDescriptor;
520
+ nextDescriptor += 1;
521
+ openEntries.set(descriptor, { handle: handle, path: file, readable: spec.readable, writable: spec.writable });
522
+ return descriptor;
523
+ }
524
+ function closeSync(descriptor) {
525
+ const entry = resolveEntry(descriptor, 'close');
526
+ openEntries.delete(Number(descriptor));
527
+ wrapCall('close', entry.path, function () {
528
+ entry.handle.close();
529
+ });
530
+ }
531
+ function readSync(descriptor, buffer, offset, length, position) {
532
+ const entry = resolveEntry(descriptor, 'read');
533
+ if (!(buffer instanceof Uint8Array)) {
534
+ throw new TypeError('The "buffer" argument must be an instance of Buffer, TypedArray, or DataView.');
535
+ }
536
+ const start = offset === undefined || offset === null ? 0 : Number(offset);
537
+ const count = length === undefined || length === null ? buffer.length - start : Number(length);
538
+ const data = wrapCall('read', entry.path, function () {
539
+ return entry.handle.read(position === undefined || position === null ? null : Number(position), count);
540
+ });
541
+ buffer.set(data, start);
542
+ return data.length;
543
+ }
544
+ function writeSync(descriptor, data, a, b, c) {
545
+ const entry = resolveEntry(descriptor, 'write');
546
+ if (typeof data === 'string') {
547
+ // Node 的字符串形式:writeSync(fd, string, position?, encoding?)
548
+ const position = a === undefined || a === null ? null : Number(a);
549
+ const encoding = b === undefined ? 'utf8' : String(b);
550
+ const bytes = buffer_1.Buffer.from(data, encoding);
551
+ return wrapCall('write', entry.path, function () {
552
+ return entry.handle.write(position, bytes);
553
+ });
554
+ }
555
+ if (!(data instanceof Uint8Array)) {
556
+ throw new TypeError('The "buffer" argument must be an instance of Buffer, TypedArray, or DataView.');
557
+ }
558
+ const offset = a === undefined || a === null ? 0 : Number(a);
559
+ const length = b === undefined || b === null ? data.length - offset : Number(b);
560
+ const position = c === undefined || c === null ? null : Number(c);
561
+ const slice = data.subarray(offset, offset + length);
562
+ return wrapCall('write', entry.path, function () {
563
+ return entry.handle.write(position, slice);
564
+ });
565
+ }
566
+ function fstatSync(descriptor, options) {
567
+ const entry = resolveEntry(descriptor, 'fstat');
568
+ const throwIfNoEntry = options !== null && typeof options === 'object' &&
569
+ options.throwIfNoEntry === false
570
+ ? false
571
+ : true;
572
+ const current = ready();
573
+ try {
574
+ return new Stats(current.stat(entry.path, true));
575
+ }
576
+ catch (failure) {
577
+ if (!throwIfNoEntry && isMissing(failure)) {
578
+ return new Stats({
579
+ isFile: true,
580
+ isDirectory: false,
581
+ isSymbolicLink: false,
582
+ size: entry.handle.size(),
583
+ mode: 0o666,
584
+ atimeMs: 0,
585
+ mtimeMs: 0,
586
+ ctimeMs: 0,
587
+ birthtimeMs: 0
588
+ });
589
+ }
590
+ throw (0, errors_1.withContext)(failure, 'fstat', entry.path);
591
+ }
592
+ }
593
+ function ftruncateSync(descriptor, length) {
594
+ const entry = resolveEntry(descriptor, 'ftruncate');
595
+ const size = length === undefined ? 0 : Number(length);
596
+ wrapCall('ftruncate', entry.path, function () {
597
+ entry.handle.truncate(size);
598
+ });
599
+ }
600
+ function fsyncSync(descriptor) {
601
+ const entry = resolveEntry(descriptor, 'fsync');
602
+ wrapCall('fsync', entry.path, function () {
603
+ entry.handle.sync();
604
+ });
605
+ }
606
+ /**
607
+ * 把同步面包装成 Node 的回调形式(最后一个参数是回调)。
608
+ * 与 fs/promises 同样的取舍:宿主只有同步通道,所以是"接口异步、执行同步"。
609
+ */
610
+ function withCallback(syncFunction, args) {
611
+ const done = args[args.length - 1];
612
+ if (typeof done !== 'function') {
613
+ throw new TypeError('The "callback" argument must be of type function.');
614
+ }
615
+ const forward = args.slice(0, args.length - 1);
616
+ queueMicrotask(function () {
617
+ try {
618
+ done(null, syncFunction.apply(null, forward));
619
+ }
620
+ catch (failure) {
621
+ done(failure);
622
+ }
623
+ });
624
+ }
625
+ function readFile(...args) {
626
+ withCallback(readFileSync, args);
627
+ }
628
+ function writeFile(...args) {
629
+ withCallback(writeFileSync, args);
630
+ }
631
+ function appendFile(...args) {
632
+ withCallback(appendFileSync, args);
633
+ }
634
+ function stat(...args) {
635
+ withCallback(statSync, args);
636
+ }
637
+ function lstat(...args) {
638
+ withCallback(lstatSync, args);
639
+ }
640
+ function readdir(...args) {
641
+ withCallback(readdirSync, args);
642
+ }
643
+ function mkdir(...args) {
644
+ withCallback(mkdirSync, args);
645
+ }
646
+ function rm(...args) {
647
+ withCallback(rmSync, args);
648
+ }
649
+ function unlink(...args) {
650
+ withCallback(unlinkSync, args);
651
+ }
652
+ function rmdir(...args) {
653
+ withCallback(rmdirSync, args);
654
+ }
655
+ function rename(...args) {
656
+ withCallback(renameSync, args);
657
+ }
658
+ function copyFile(...args) {
659
+ withCallback(copyFileSync, args);
660
+ }
661
+ function realpath(...args) {
662
+ withCallback(realpathSync, args);
663
+ }
664
+ function access(...args) {
665
+ withCallback(accessSync, args);
666
+ }
667
+ function mkdtemp(...args) {
668
+ withCallback(mkdtempSync, args);
669
+ }
670
+ function open(...args) {
671
+ withCallback(openSync, args);
672
+ }
673
+ function close(...args) {
674
+ withCallback(closeSync, args);
675
+ }
676
+ function read(...args) {
677
+ withCallback(readSync, args);
678
+ }
679
+ function write(...args) {
680
+ withCallback(writeSync, args);
681
+ }
682
+ function fstat(...args) {
683
+ withCallback(fstatSync, args);
684
+ }
685
+ function ftruncate(...args) {
686
+ withCallback(ftruncateSync, args);
687
+ }
688
+ function fsync(...args) {
689
+ withCallback(fsyncSync, args);
690
+ }
691
+ /** Node 的 fs.exists 回调只收一个布尔值,是唯一不带 error 的形态。 */
692
+ function exists(target, callback) {
693
+ if (typeof callback !== 'function') {
694
+ throw new TypeError('The "callback" argument must be of type function.');
695
+ }
696
+ const done = callback;
697
+ queueMicrotask(function () {
698
+ done(existsSync(target));
699
+ });
700
+ }
701
+ // ------------------------------------------------------------------ 流式接口
702
+ /**
703
+ * fs.createReadStream。
704
+ *
705
+ * 与 Node 的差异(本库的驱动层没有 fd 概念,因此是"按需整块读 + 切片下发"):
706
+ * - 首次 _read 时把整个文件读进内存,之后按 highWaterMark 切片,
707
+ * 所以内存占用不是流式的;
708
+ * - 'open' 事件仍会发,但参数是 null(没有真实 fd)。
709
+ */
710
+ function createReadStream(target, options) {
711
+ const file = toAbsolute(target, 'path');
712
+ const spec = parseFlag(options === undefined ? undefined : options.flags);
713
+ if (!spec.readable) {
714
+ throw (0, errors_1.createError)('EBADF', 'open', file);
715
+ }
716
+ const highWaterMark = options !== undefined && typeof options.highWaterMark === 'number'
717
+ ? options.highWaterMark
718
+ : 65536;
719
+ const startAt = options !== undefined && typeof options.start === 'number' ? options.start : 0;
720
+ const endAt = options !== undefined && typeof options.end === 'number' ? options.end : Infinity;
721
+ let opened = false;
722
+ let failed = false;
723
+ let position = startAt;
724
+ let payload = null;
725
+ let readable = null;
726
+ const open = function () {
727
+ const self = readable;
728
+ if (opened || failed) {
729
+ return;
730
+ }
731
+ try {
732
+ const current = ready();
733
+ payload = wrapCall('open', file, function () {
734
+ return current.readFileBytes(file);
735
+ });
736
+ opened = true;
737
+ // 没有真实 fd,'open' 的参数如实给 null
738
+ self.emit('open', null);
739
+ }
740
+ catch (failure) {
741
+ failed = true;
742
+ self.destroy(failure);
743
+ }
744
+ };
745
+ readable = new streamModule.Readable({
746
+ highWaterMark: highWaterMark,
747
+ encoding: options === undefined ? undefined : options.encoding,
748
+ read: function () {
749
+ const self = readable;
750
+ if (!opened) {
751
+ open();
752
+ if (!opened) {
753
+ return;
754
+ }
755
+ }
756
+ const bytes = payload;
757
+ if (position >= bytes.length || position > endAt) {
758
+ self.push(null);
759
+ return;
760
+ }
761
+ const upper = Math.min(bytes.length, endAt === Infinity ? bytes.length : endAt + 1, position + highWaterMark);
762
+ self.push(bytes.subarray(position, upper));
763
+ position = upper;
764
+ },
765
+ destroy: function (error, callback) {
766
+ callback(error);
767
+ }
768
+ });
769
+ // 与 Node 一致:构造后就打开文件并发 'open',因此只监听 'open' 的代码不会挂住
770
+ schedule(function () {
771
+ open();
772
+ });
773
+ return readable;
774
+ }
775
+ function schedule(task) {
776
+ queueMicrotask(task);
777
+ }
778
+ /**
779
+ * fs.createWriteStream。
780
+ *
781
+ * 驱动层没有 fd,但写入语义可以保持流式:首次写按 flag 决定是否截断,
782
+ * 之后逐块追加,内存占用与流式一致。
783
+ */
784
+ function createWriteStream(target, options) {
785
+ const file = toAbsolute(target, 'path');
786
+ // 写流的默认 flag 是 'w'(读流才是 'r')—— 与 writeFileSync 同类,踩过一次
787
+ const spec = parseFlag(options === undefined || options.flags === undefined ? 'w' : options.flags);
788
+ if (!spec.writable) {
789
+ throw (0, errors_1.createError)('EBADF', 'write', file);
790
+ }
791
+ const highWaterMark = options !== undefined && typeof options.highWaterMark === 'number'
792
+ ? options.highWaterMark
793
+ : 16384;
794
+ let wroteAny = false;
795
+ let writable = null;
796
+ writable = new streamModule.Writable({
797
+ highWaterMark: highWaterMark,
798
+ write: function (chunk, encoding, callback) {
799
+ try {
800
+ const current = ready();
801
+ const bytes = chunk instanceof Uint8Array
802
+ ? chunk
803
+ : buffer_1.Buffer.from(String(chunk), (encoding === 'buffer' ? 'utf8' : encoding));
804
+ const append = wroteAny || spec.append;
805
+ const exclusive = !wroteAny && spec.exclusive;
806
+ wrapCall('write', file, function () {
807
+ current.writeFileBytes(file, bytes, append, exclusive);
808
+ });
809
+ wroteAny = true;
810
+ callback(null);
811
+ }
812
+ catch (failure) {
813
+ callback(failure);
814
+ }
815
+ },
816
+ final: function (callback) {
817
+ // Node 的 'w' 即使一个字节都没写也会建出空文件
818
+ if (!wroteAny && spec.truncate) {
819
+ try {
820
+ const current = ready();
821
+ wrapCall('open', file, function () {
822
+ current.writeFileBytes(file, new Uint8Array(0), false, spec.exclusive);
823
+ });
824
+ }
825
+ catch (failure) {
826
+ callback(failure);
827
+ return;
828
+ }
829
+ }
830
+ callback(null);
831
+ }
832
+ });
833
+ void writable;
834
+ return writable;
835
+ }
836
+ // ------------------------------------------------------------------ 常量
837
+ const constants = {
838
+ F_OK: 0,
839
+ R_OK: 4,
840
+ W_OK: 2,
841
+ X_OK: 1,
842
+ COPYFILE_EXCL: 1,
843
+ COPYFILE_FICLONE: 2,
844
+ COPYFILE_FICLONE_FORCE: 4,
845
+ // libuv 自己的那套镜像常量,Node 也导出
846
+ UV_FS_COPYFILE_EXCL: 1,
847
+ UV_FS_COPYFILE_FICLONE: 2,
848
+ UV_FS_COPYFILE_FICLONE_FORCE: 4,
849
+ O_RDONLY: 0,
850
+ O_WRONLY: 1,
851
+ O_RDWR: 2,
852
+ O_CREAT: 64,
853
+ O_EXCL: 128,
854
+ O_TRUNC: 512,
855
+ O_APPEND: 1024,
856
+ UV_FS_O_FILEMAP: 0,
857
+ UV_FS_SYMLINK_DIR: 1,
858
+ UV_FS_SYMLINK_JUNCTION: 2,
859
+ UV_DIRENT_UNKNOWN: 0,
860
+ UV_DIRENT_FILE: 1,
861
+ UV_DIRENT_DIR: 2,
862
+ UV_DIRENT_LINK: 3,
863
+ UV_DIRENT_FIFO: 4,
864
+ UV_DIRENT_SOCKET: 5,
865
+ UV_DIRENT_CHAR: 6,
866
+ UV_DIRENT_BLOCK: 7,
867
+ // POSIX 文件类型与权限位(Linux/Android 的值)
868
+ S_IFMT: 61440,
869
+ S_IFREG: 32768,
870
+ S_IFDIR: 16384,
871
+ S_IFCHR: 8192,
872
+ S_IFIFO: 4096,
873
+ S_IFLNK: 40960,
874
+ S_IRUSR: 256,
875
+ S_IWUSR: 128,
876
+ S_IXUSR: 64,
877
+ S_IRGRP: 32,
878
+ S_IWGRP: 16,
879
+ S_IXGRP: 8,
880
+ S_IROTH: 4,
881
+ S_IWOTH: 2,
882
+ S_IXOTH: 1
883
+ };
884
+ const fs = {
885
+ readFileSync: readFileSync,
886
+ writeFileSync: writeFileSync,
887
+ appendFileSync: appendFileSync,
888
+ existsSync: existsSync,
889
+ statSync: statSync,
890
+ lstatSync: lstatSync,
891
+ readdirSync: readdirSync,
892
+ mkdirSync: mkdirSync,
893
+ rmSync: rmSync,
894
+ unlinkSync: unlinkSync,
895
+ rmdirSync: rmdirSync,
896
+ renameSync: renameSync,
897
+ copyFileSync: copyFileSync,
898
+ realpathSync: realpathSync,
899
+ readlinkSync: readlinkSync,
900
+ symlinkSync: symlinkSync,
901
+ chmodSync: chmodSync,
902
+ truncateSync: truncateSync,
903
+ utimesSync: utimesSync,
904
+ accessSync: accessSync,
905
+ mkdtempSync: mkdtempSync,
906
+ openSync: openSync,
907
+ closeSync: closeSync,
908
+ readSync: readSync,
909
+ writeSync: writeSync,
910
+ fstatSync: fstatSync,
911
+ ftruncateSync: ftruncateSync,
912
+ fsyncSync: fsyncSync,
913
+ fdatasyncSync: fsyncSync,
914
+ readFile: readFile,
915
+ writeFile: writeFile,
916
+ appendFile: appendFile,
917
+ stat: stat,
918
+ lstat: lstat,
919
+ readdir: readdir,
920
+ mkdir: mkdir,
921
+ rm: rm,
922
+ unlink: unlink,
923
+ rmdir: rmdir,
924
+ rename: rename,
925
+ copyFile: copyFile,
926
+ realpath: realpath,
927
+ access: access,
928
+ mkdtemp: mkdtemp,
929
+ exists: exists,
930
+ open: open,
931
+ close: close,
932
+ read: read,
933
+ write: write,
934
+ fstat: fstat,
935
+ ftruncate: ftruncate,
936
+ fsync: fsync,
937
+ createReadStream: createReadStream,
938
+ createWriteStream: createWriteStream,
939
+ Stats: Stats,
940
+ Dirent: Dirent,
941
+ constants: constants,
942
+ env: env
943
+ };
944
+ module.exports = fs;