@tybys/wasm-util 0.10.1 → 0.10.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/wasm-util.esm-bundler.js +224 -50
- package/dist/wasm-util.esm.js +224 -50
- package/dist/wasm-util.esm.min.js +1 -1
- package/dist/wasm-util.js +224 -50
- package/dist/wasm-util.min.js +1 -1
- package/lib/cjs/wasi/path.js +142 -0
- package/lib/cjs/wasi/preview1.js +84 -51
- package/lib/mjs/wasi/path.mjs +142 -0
- package/lib/mjs/wasi/preview1.mjs +82 -50
- package/package.json +1 -1
package/lib/cjs/wasi/preview1.js
CHANGED
|
@@ -1,8 +1,28 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.WASI = void 0;
|
|
3
|
+
exports.WASI = exports.ensureMemoryFor = void 0;
|
|
4
4
|
const webassembly_1 = require("../webassembly");
|
|
5
5
|
const path_1 = require("./path");
|
|
6
|
+
// Linux fcntl flag bits ↔ Windows libuv flag bits. `pathOpen()` builds
|
|
7
|
+
// `flagsRes` using Linux constants (O_CREAT=0x40, O_EXCL=0x80,
|
|
8
|
+
// O_APPEND=0x400). Windows libuv expects different bits (O_CREAT=0x100,
|
|
9
|
+
// O_EXCL=0x400, O_APPEND=0x8). Without translation,
|
|
10
|
+
// `fs.openSync(path, 0x241 /* L:WRONLY|CREAT|TRUNC */)` is rejected
|
|
11
|
+
// with EINVAL because Linux's 0x40 happens to mean O_TEMPORARY on
|
|
12
|
+
// Windows — and O_TEMPORARY without O_CREAT is invalid.
|
|
13
|
+
const _isWin32Flags = typeof process !== 'undefined' && process.platform === 'win32';
|
|
14
|
+
function _toWinOpenFlags(f) {
|
|
15
|
+
let r = f & 3; // RDONLY/WRONLY/RDWR — same on both
|
|
16
|
+
if ((f & 0x40) !== 0)
|
|
17
|
+
r |= 0x100; // O_CREAT: Linux 0x40 -> Windows 0x100
|
|
18
|
+
if ((f & 0x80) !== 0)
|
|
19
|
+
r |= 0x400; // O_EXCL: Linux 0x80 -> Windows 0x400
|
|
20
|
+
if ((f & 0x200) !== 0)
|
|
21
|
+
r |= 0x200; // O_TRUNC: same value on both
|
|
22
|
+
if ((f & 0x400) !== 0)
|
|
23
|
+
r |= 0x8; // O_APPEND: Linux 0x400 -> Windows 0x8
|
|
24
|
+
return r;
|
|
25
|
+
}
|
|
6
26
|
const types_1 = require("./types");
|
|
7
27
|
const fd_1 = require("./fd");
|
|
8
28
|
const error_1 = require("./error");
|
|
@@ -32,8 +52,19 @@ function copyMemory(targets, src) {
|
|
|
32
52
|
const _memory = new WeakMap();
|
|
33
53
|
const _wasi = new WeakMap();
|
|
34
54
|
const _fs = new WeakMap();
|
|
35
|
-
function
|
|
36
|
-
|
|
55
|
+
function ensureMemoryFor(memory, end) {
|
|
56
|
+
let buffer = memory.buffer;
|
|
57
|
+
if (end > buffer.byteLength) {
|
|
58
|
+
memory.grow(0);
|
|
59
|
+
buffer = memory.buffer;
|
|
60
|
+
}
|
|
61
|
+
return buffer;
|
|
62
|
+
}
|
|
63
|
+
exports.ensureMemoryFor = ensureMemoryFor;
|
|
64
|
+
function getMemory(wasi, end = 0) {
|
|
65
|
+
const memory = _memory.get(wasi);
|
|
66
|
+
ensureMemoryFor(memory, end);
|
|
67
|
+
return memory;
|
|
37
68
|
}
|
|
38
69
|
function getFs(wasi) {
|
|
39
70
|
const fs = _fs.get(wasi);
|
|
@@ -162,9 +193,10 @@ class WASI {
|
|
|
162
193
|
if (argv === 0 || argv_buf === 0) {
|
|
163
194
|
return types_1.WasiErrno.EINVAL;
|
|
164
195
|
}
|
|
165
|
-
const { HEAPU8, view } = getMemory(this);
|
|
166
196
|
const wasi = _wasi.get(this);
|
|
167
197
|
const args = wasi.args;
|
|
198
|
+
const argsSize = encoder.encode(args.join('\0') + '\0').length;
|
|
199
|
+
const { HEAPU8, view } = getMemory(this, Math.max(argv + args.length * 4, argv_buf + argsSize));
|
|
168
200
|
for (let i = 0; i < args.length; ++i) {
|
|
169
201
|
const arg = args[i];
|
|
170
202
|
view.setInt32(argv, argv_buf, true);
|
|
@@ -181,7 +213,7 @@ class WASI {
|
|
|
181
213
|
if (argc === 0 || argv_buf_size === 0) {
|
|
182
214
|
return types_1.WasiErrno.EINVAL;
|
|
183
215
|
}
|
|
184
|
-
const { view } = getMemory(this);
|
|
216
|
+
const { view } = getMemory(this, Math.max(argc + 4, argv_buf_size + 4));
|
|
185
217
|
const wasi = _wasi.get(this);
|
|
186
218
|
const args = wasi.args;
|
|
187
219
|
view.setUint32(argc, args.length, true);
|
|
@@ -194,9 +226,10 @@ class WASI {
|
|
|
194
226
|
if (environ === 0 || environ_buf === 0) {
|
|
195
227
|
return types_1.WasiErrno.EINVAL;
|
|
196
228
|
}
|
|
197
|
-
const { HEAPU8, view } = getMemory(this);
|
|
198
229
|
const wasi = _wasi.get(this);
|
|
199
230
|
const env = wasi.env;
|
|
231
|
+
const envSize = encoder.encode(env.join('\0') + '\0').length;
|
|
232
|
+
const { HEAPU8, view } = getMemory(this, Math.max(environ + env.length * 4, environ_buf + envSize));
|
|
200
233
|
for (let i = 0; i < env.length; ++i) {
|
|
201
234
|
const pair = env[i];
|
|
202
235
|
view.setInt32(environ, environ_buf, true);
|
|
@@ -213,7 +246,7 @@ class WASI {
|
|
|
213
246
|
if (len === 0 || buflen === 0) {
|
|
214
247
|
return types_1.WasiErrno.EINVAL;
|
|
215
248
|
}
|
|
216
|
-
const { view } = getMemory(this);
|
|
249
|
+
const { view } = getMemory(this, Math.max(len + 4, buflen + 4));
|
|
217
250
|
const wasi = _wasi.get(this);
|
|
218
251
|
view.setUint32(len, wasi.env.length, true);
|
|
219
252
|
view.setUint32(buflen, encoder.encode(wasi.env.join('\0') + '\0').length, true);
|
|
@@ -224,7 +257,7 @@ class WASI {
|
|
|
224
257
|
if (resolution === 0) {
|
|
225
258
|
return types_1.WasiErrno.EINVAL;
|
|
226
259
|
}
|
|
227
|
-
const { view } = getMemory(this);
|
|
260
|
+
const { view } = getMemory(this, resolution + 8);
|
|
228
261
|
switch (id) {
|
|
229
262
|
case types_1.WasiClockid.REALTIME:
|
|
230
263
|
view.setBigUint64(resolution, BigInt(1000000), true);
|
|
@@ -242,7 +275,7 @@ class WASI {
|
|
|
242
275
|
if (time === 0) {
|
|
243
276
|
return types_1.WasiErrno.EINVAL;
|
|
244
277
|
}
|
|
245
|
-
const { view } = getMemory(this);
|
|
278
|
+
const { view } = getMemory(this, time + 8);
|
|
246
279
|
switch (id) {
|
|
247
280
|
case types_1.WasiClockid.REALTIME:
|
|
248
281
|
view.setBigUint64(time, BigInt(Date.now()) * BigInt(1000000), true);
|
|
@@ -270,7 +303,7 @@ class WASI {
|
|
|
270
303
|
}
|
|
271
304
|
const wasi = _wasi.get(this);
|
|
272
305
|
const fileDescriptor = wasi.fds.get(fd, BigInt(0), BigInt(0));
|
|
273
|
-
const { view } = getMemory(this);
|
|
306
|
+
const { view } = getMemory(this, fdstat + 24);
|
|
274
307
|
view.setUint16(fdstat, fileDescriptor.type, true);
|
|
275
308
|
view.setUint16(fdstat + 2, 0, true);
|
|
276
309
|
view.setBigUint64(fdstat + 8, fileDescriptor.rightsBase, true);
|
|
@@ -311,7 +344,7 @@ class WASI {
|
|
|
311
344
|
}
|
|
312
345
|
if (fileDescriptor.preopen !== 1)
|
|
313
346
|
return types_1.WasiErrno.EINVAL;
|
|
314
|
-
const { view } = getMemory(this);
|
|
347
|
+
const { view } = getMemory(this, prestat + 8);
|
|
315
348
|
// preopen type is dir(0)
|
|
316
349
|
view.setUint32(prestat, 0, true);
|
|
317
350
|
view.setUint32(prestat + 4, encoder.encode(fileDescriptor.path).length, true);
|
|
@@ -331,7 +364,7 @@ class WASI {
|
|
|
331
364
|
const size = buffer.length;
|
|
332
365
|
if (size > path_len)
|
|
333
366
|
return types_1.WasiErrno.ENOBUFS;
|
|
334
|
-
const { HEAPU8 } = getMemory(this);
|
|
367
|
+
const { HEAPU8 } = getMemory(this, path + size);
|
|
335
368
|
HEAPU8.set(buffer, path);
|
|
336
369
|
return types_1.WasiErrno.ESUCCESS;
|
|
337
370
|
});
|
|
@@ -345,7 +378,7 @@ class WASI {
|
|
|
345
378
|
const wasi = _wasi.get(this);
|
|
346
379
|
const fileDescriptor = wasi.fds.get(fd, types_1.WasiRights.FD_SEEK, BigInt(0));
|
|
347
380
|
const r = fileDescriptor.seek(offset, whence);
|
|
348
|
-
const { view } = getMemory(this);
|
|
381
|
+
const { view } = getMemory(this, newOffset + 8);
|
|
349
382
|
view.setBigUint64(newOffset, r, true);
|
|
350
383
|
return types_1.WasiErrno.ESUCCESS;
|
|
351
384
|
});
|
|
@@ -353,7 +386,7 @@ class WASI {
|
|
|
353
386
|
const wasi = _wasi.get(this);
|
|
354
387
|
const fileDescriptor = wasi.fds.get(fd, types_1.WasiRights.FD_TELL, BigInt(0));
|
|
355
388
|
const pos = BigInt(fileDescriptor.pos);
|
|
356
|
-
const { view } = getMemory(this);
|
|
389
|
+
const { view } = getMemory(this, Number(offset) + 8);
|
|
357
390
|
view.setBigUint64(Number(offset), pos, true);
|
|
358
391
|
return types_1.WasiErrno.ESUCCESS;
|
|
359
392
|
});
|
|
@@ -366,7 +399,7 @@ class WASI {
|
|
|
366
399
|
if (in_ptr === 0 || out_ptr === 0 || nsubscriptions === 0 || nevents === 0) {
|
|
367
400
|
return types_1.WasiErrno.EINVAL;
|
|
368
401
|
}
|
|
369
|
-
const { view } = getMemory(this);
|
|
402
|
+
const { view } = getMemory(this, Math.max(in_ptr + nsubscriptions * 48, out_ptr + nsubscriptions * 32, nevents + 4));
|
|
370
403
|
view.setUint32(nevents, 0, true);
|
|
371
404
|
let i = 0;
|
|
372
405
|
let timer_userdata = BigInt(0);
|
|
@@ -485,7 +518,7 @@ class WASI {
|
|
|
485
518
|
return types_1.WasiErrno.EINVAL;
|
|
486
519
|
}
|
|
487
520
|
buf_len = Number(buf_len);
|
|
488
|
-
const { HEAPU8, view } = getMemory(this);
|
|
521
|
+
const { HEAPU8, view } = getMemory(this, buf + buf_len);
|
|
489
522
|
if ((typeof SharedArrayBuffer === 'function' && HEAPU8.buffer instanceof SharedArrayBuffer) ||
|
|
490
523
|
(Object.prototype.toString.call(HEAPU8.buffer) === '[object SharedArrayBuffer]')) {
|
|
491
524
|
for (let i = buf; i < buf + buf_len; ++i) {
|
|
@@ -507,7 +540,7 @@ class WASI {
|
|
|
507
540
|
return types_1.WasiErrno.EINVAL;
|
|
508
541
|
}
|
|
509
542
|
buf_len = Number(buf_len);
|
|
510
|
-
const { view } = getMemory(this);
|
|
543
|
+
const { view } = getMemory(this, buf + buf_len);
|
|
511
544
|
for (let i = buf; i < buf + buf_len; ++i) {
|
|
512
545
|
view.setUint8(i, Math.floor(Math.random() * 256));
|
|
513
546
|
}
|
|
@@ -600,7 +633,7 @@ class WASI {
|
|
|
600
633
|
const fileDescriptor = wasi.fds.get(fd, types_1.WasiRights.FD_FILESTAT_GET, BigInt(0));
|
|
601
634
|
const fs = getFs(this);
|
|
602
635
|
const stat = fs.fstatSync(fileDescriptor.fd, { bigint: true });
|
|
603
|
-
const { view } = getMemory(this);
|
|
636
|
+
const { view } = getMemory(this, buf + 64);
|
|
604
637
|
(0, fd_1.toFileStat)(view, buf, stat);
|
|
605
638
|
return types_1.WasiErrno.ESUCCESS;
|
|
606
639
|
}, async function fd_filestat_get(fd, buf) {
|
|
@@ -611,7 +644,7 @@ class WASI {
|
|
|
611
644
|
const fileDescriptor = wasi.fds.get(fd, types_1.WasiRights.FD_FILESTAT_GET, BigInt(0));
|
|
612
645
|
const h = fileDescriptor.fd;
|
|
613
646
|
const stat = await h.stat({ bigint: true });
|
|
614
|
-
const { view } = getMemory(this);
|
|
647
|
+
const { view } = getMemory(this, buf + 64);
|
|
615
648
|
(0, fd_1.toFileStat)(view, buf, stat);
|
|
616
649
|
return types_1.WasiErrno.ESUCCESS;
|
|
617
650
|
}, ['i32', 'i32'], ['i32']);
|
|
@@ -662,7 +695,7 @@ class WASI {
|
|
|
662
695
|
if ((iovs === 0 && iovslen) || size === 0 || offset > INT64_MAX) {
|
|
663
696
|
return types_1.WasiErrno.EINVAL;
|
|
664
697
|
}
|
|
665
|
-
const { HEAPU8, view } = getMemory(this);
|
|
698
|
+
const { HEAPU8, view } = getMemory(this, Math.max(iovs + Number(iovslen) * 8, size + 4));
|
|
666
699
|
const wasi = _wasi.get(this);
|
|
667
700
|
const fileDescriptor = wasi.fds.get(fd, types_1.WasiRights.FD_READ | types_1.WasiRights.FD_SEEK, BigInt(0));
|
|
668
701
|
if (!iovslen) {
|
|
@@ -698,7 +731,7 @@ class WASI {
|
|
|
698
731
|
if ((iovs === 0 && iovslen) || size === 0 || offset > INT64_MAX) {
|
|
699
732
|
return types_1.WasiErrno.EINVAL;
|
|
700
733
|
}
|
|
701
|
-
const { HEAPU8, view } = getMemory(this);
|
|
734
|
+
const { HEAPU8, view } = getMemory(this, Math.max(iovs + Number(iovslen) * 8, size + 4));
|
|
702
735
|
const wasi = _wasi.get(this);
|
|
703
736
|
const fileDescriptor = wasi.fds.get(fd, types_1.WasiRights.FD_READ | types_1.WasiRights.FD_SEEK, BigInt(0));
|
|
704
737
|
if (!iovslen) {
|
|
@@ -727,7 +760,7 @@ class WASI {
|
|
|
727
760
|
if ((iovs === 0 && iovslen) || size === 0 || offset > INT64_MAX) {
|
|
728
761
|
return types_1.WasiErrno.EINVAL;
|
|
729
762
|
}
|
|
730
|
-
const { HEAPU8, view } = getMemory(this);
|
|
763
|
+
const { HEAPU8, view } = getMemory(this, Math.max(iovs + Number(iovslen) * 8, size + 4));
|
|
731
764
|
const wasi = _wasi.get(this);
|
|
732
765
|
const fileDescriptor = wasi.fds.get(fd, types_1.WasiRights.FD_WRITE | types_1.WasiRights.FD_SEEK, BigInt(0));
|
|
733
766
|
if (!iovslen) {
|
|
@@ -750,7 +783,7 @@ class WASI {
|
|
|
750
783
|
if ((iovs === 0 && iovslen) || size === 0 || offset > INT64_MAX) {
|
|
751
784
|
return types_1.WasiErrno.EINVAL;
|
|
752
785
|
}
|
|
753
|
-
const { HEAPU8, view } = getMemory(this);
|
|
786
|
+
const { HEAPU8, view } = getMemory(this, Math.max(iovs + Number(iovslen) * 8, size + 4));
|
|
754
787
|
const wasi = _wasi.get(this);
|
|
755
788
|
const fileDescriptor = wasi.fds.get(fd, types_1.WasiRights.FD_WRITE | types_1.WasiRights.FD_SEEK, BigInt(0));
|
|
756
789
|
if (!iovslen) {
|
|
@@ -773,7 +806,7 @@ class WASI {
|
|
|
773
806
|
if ((iovs === 0 && iovslen) || size === 0) {
|
|
774
807
|
return types_1.WasiErrno.EINVAL;
|
|
775
808
|
}
|
|
776
|
-
const { HEAPU8, view } = getMemory(this);
|
|
809
|
+
const { HEAPU8, view } = getMemory(this, Math.max(iovs + Number(iovslen) * 8, size + 4));
|
|
777
810
|
const wasi = _wasi.get(this);
|
|
778
811
|
const fileDescriptor = wasi.fds.get(fd, types_1.WasiRights.FD_READ, BigInt(0));
|
|
779
812
|
if (!iovslen) {
|
|
@@ -820,7 +853,7 @@ class WASI {
|
|
|
820
853
|
if ((iovs === 0 && iovslen) || size === 0) {
|
|
821
854
|
return types_1.WasiErrno.EINVAL;
|
|
822
855
|
}
|
|
823
|
-
const { HEAPU8, view } = getMemory(this);
|
|
856
|
+
const { HEAPU8, view } = getMemory(this, Math.max(iovs + Number(iovslen) * 8, size + 4));
|
|
824
857
|
const wasi = _wasi.get(this);
|
|
825
858
|
const fileDescriptor = wasi.fds.get(fd, types_1.WasiRights.FD_READ, BigInt(0));
|
|
826
859
|
if (!iovslen) {
|
|
@@ -864,7 +897,7 @@ class WASI {
|
|
|
864
897
|
const fileDescriptor = wasi.fds.get(fd, types_1.WasiRights.FD_READDIR, BigInt(0));
|
|
865
898
|
const fs = getFs(this);
|
|
866
899
|
const entries = fs.readdirSync(fileDescriptor.realPath, { withFileTypes: true });
|
|
867
|
-
const { HEAPU8, view } = getMemory(this);
|
|
900
|
+
const { HEAPU8, view } = getMemory(this, Math.max(buf + buf_len, bufused + 4));
|
|
868
901
|
let bufferUsed = 0;
|
|
869
902
|
for (let i = Number(cookie); i < entries.length; i++) {
|
|
870
903
|
const nameData = encoder.encode(entries[i].name);
|
|
@@ -914,7 +947,7 @@ class WASI {
|
|
|
914
947
|
const fileDescriptor = wasi.fds.get(fd, types_1.WasiRights.FD_READDIR, BigInt(0));
|
|
915
948
|
const fs = getFs(this);
|
|
916
949
|
const entries = await fs.promises.readdir(fileDescriptor.realPath, { withFileTypes: true });
|
|
917
|
-
const { HEAPU8, view } = getMemory(this);
|
|
950
|
+
const { HEAPU8, view } = getMemory(this, Math.max(buf + buf_len, bufused + 4));
|
|
918
951
|
let bufferUsed = 0;
|
|
919
952
|
for (let i = Number(cookie); i < entries.length; i++) {
|
|
920
953
|
const nameData = encoder.encode(entries[i].name);
|
|
@@ -982,7 +1015,7 @@ class WASI {
|
|
|
982
1015
|
if ((iovs === 0 && iovslen) || size === 0) {
|
|
983
1016
|
return types_1.WasiErrno.EINVAL;
|
|
984
1017
|
}
|
|
985
|
-
const { HEAPU8, view } = getMemory(this);
|
|
1018
|
+
const { HEAPU8, view } = getMemory(this, Math.max(iovs + Number(iovslen) * 8, size + 4));
|
|
986
1019
|
const wasi = _wasi.get(this);
|
|
987
1020
|
const fileDescriptor = wasi.fds.get(fd, types_1.WasiRights.FD_WRITE, BigInt(0));
|
|
988
1021
|
if (!iovslen) {
|
|
@@ -1012,7 +1045,7 @@ class WASI {
|
|
|
1012
1045
|
if ((iovs === 0 && iovslen) || size === 0) {
|
|
1013
1046
|
return types_1.WasiErrno.EINVAL;
|
|
1014
1047
|
}
|
|
1015
|
-
const { HEAPU8, view } = getMemory(this);
|
|
1048
|
+
const { HEAPU8, view } = getMemory(this, Math.max(iovs + Number(iovslen) * 8, size + 4));
|
|
1016
1049
|
const wasi = _wasi.get(this);
|
|
1017
1050
|
const fileDescriptor = wasi.fds.get(fd, types_1.WasiRights.FD_WRITE, BigInt(0));
|
|
1018
1051
|
if (!iovslen) {
|
|
@@ -1042,7 +1075,7 @@ class WASI {
|
|
|
1042
1075
|
if (path === 0) {
|
|
1043
1076
|
return types_1.WasiErrno.EINVAL;
|
|
1044
1077
|
}
|
|
1045
|
-
const { HEAPU8 } = getMemory(this);
|
|
1078
|
+
const { HEAPU8 } = getMemory(this, path + path_len);
|
|
1046
1079
|
const wasi = _wasi.get(this);
|
|
1047
1080
|
const fileDescriptor = wasi.fds.get(fd, types_1.WasiRights.PATH_CREATE_DIRECTORY, BigInt(0));
|
|
1048
1081
|
let pathString = decoder.decode((0, util_1.unsharedSlice)(HEAPU8, path, path + path_len));
|
|
@@ -1056,7 +1089,7 @@ class WASI {
|
|
|
1056
1089
|
if (path === 0) {
|
|
1057
1090
|
return types_1.WasiErrno.EINVAL;
|
|
1058
1091
|
}
|
|
1059
|
-
const { HEAPU8 } = getMemory(this);
|
|
1092
|
+
const { HEAPU8 } = getMemory(this, path + path_len);
|
|
1060
1093
|
const wasi = _wasi.get(this);
|
|
1061
1094
|
const fileDescriptor = wasi.fds.get(fd, types_1.WasiRights.PATH_CREATE_DIRECTORY, BigInt(0));
|
|
1062
1095
|
let pathString = decoder.decode((0, util_1.unsharedSlice)(HEAPU8, path, path + path_len));
|
|
@@ -1072,7 +1105,7 @@ class WASI {
|
|
|
1072
1105
|
if (path === 0 || filestat === 0) {
|
|
1073
1106
|
return types_1.WasiErrno.EINVAL;
|
|
1074
1107
|
}
|
|
1075
|
-
const { HEAPU8, view } = getMemory(this);
|
|
1108
|
+
const { HEAPU8, view } = getMemory(this, Math.max(path + path_len, filestat + 64));
|
|
1076
1109
|
const wasi = _wasi.get(this);
|
|
1077
1110
|
const fileDescriptor = wasi.fds.get(fd, types_1.WasiRights.PATH_FILESTAT_GET, BigInt(0));
|
|
1078
1111
|
let pathString = decoder.decode((0, util_1.unsharedSlice)(HEAPU8, path, path + path_len));
|
|
@@ -1094,7 +1127,7 @@ class WASI {
|
|
|
1094
1127
|
if (path === 0 || filestat === 0) {
|
|
1095
1128
|
return types_1.WasiErrno.EINVAL;
|
|
1096
1129
|
}
|
|
1097
|
-
const { HEAPU8, view } = getMemory(this);
|
|
1130
|
+
const { HEAPU8, view } = getMemory(this, Math.max(path + path_len, filestat + 64));
|
|
1098
1131
|
const wasi = _wasi.get(this);
|
|
1099
1132
|
const fileDescriptor = wasi.fds.get(fd, types_1.WasiRights.PATH_FILESTAT_GET, BigInt(0));
|
|
1100
1133
|
let pathString = decoder.decode((0, util_1.unsharedSlice)(HEAPU8, path, path + path_len));
|
|
@@ -1115,7 +1148,7 @@ class WASI {
|
|
|
1115
1148
|
path_len = Number(path_len);
|
|
1116
1149
|
if (path === 0)
|
|
1117
1150
|
return types_1.WasiErrno.EINVAL;
|
|
1118
|
-
const { HEAPU8 } = getMemory(this);
|
|
1151
|
+
const { HEAPU8 } = getMemory(this, path + path_len);
|
|
1119
1152
|
const wasi = _wasi.get(this);
|
|
1120
1153
|
const fileDescriptor = wasi.fds.get(fd, types_1.WasiRights.PATH_FILESTAT_SET_TIMES, BigInt(0));
|
|
1121
1154
|
if (validateFstFlagsOrReturn(fst_flags)) {
|
|
@@ -1136,7 +1169,7 @@ class WASI {
|
|
|
1136
1169
|
path_len = Number(path_len);
|
|
1137
1170
|
if (path === 0)
|
|
1138
1171
|
return types_1.WasiErrno.EINVAL;
|
|
1139
|
-
const { HEAPU8 } = getMemory(this);
|
|
1172
|
+
const { HEAPU8 } = getMemory(this, path + path_len);
|
|
1140
1173
|
const wasi = _wasi.get(this);
|
|
1141
1174
|
const fileDescriptor = wasi.fds.get(fd, types_1.WasiRights.PATH_FILESTAT_SET_TIMES, BigInt(0));
|
|
1142
1175
|
if (validateFstFlagsOrReturn(fst_flags)) {
|
|
@@ -1171,7 +1204,7 @@ class WASI {
|
|
|
1171
1204
|
oldWrap = wasi.fds.get(old_fd, types_1.WasiRights.PATH_LINK_SOURCE, BigInt(0));
|
|
1172
1205
|
newWrap = wasi.fds.get(new_fd, types_1.WasiRights.PATH_LINK_TARGET, BigInt(0));
|
|
1173
1206
|
}
|
|
1174
|
-
const { HEAPU8 } = getMemory(this);
|
|
1207
|
+
const { HEAPU8 } = getMemory(this, Math.max(old_path + old_path_len, new_path + new_path_len));
|
|
1175
1208
|
const fs = getFs(this);
|
|
1176
1209
|
const resolvedOldPath = resolvePathSync(fs, oldWrap, decoder.decode((0, util_1.unsharedSlice)(HEAPU8, old_path, old_path + old_path_len)), old_flags);
|
|
1177
1210
|
const resolvedNewPath = (0, path_1.resolve)(newWrap.realPath, decoder.decode((0, util_1.unsharedSlice)(HEAPU8, new_path, new_path + new_path_len)));
|
|
@@ -1195,7 +1228,7 @@ class WASI {
|
|
|
1195
1228
|
oldWrap = wasi.fds.get(old_fd, types_1.WasiRights.PATH_LINK_SOURCE, BigInt(0));
|
|
1196
1229
|
newWrap = wasi.fds.get(new_fd, types_1.WasiRights.PATH_LINK_TARGET, BigInt(0));
|
|
1197
1230
|
}
|
|
1198
|
-
const { HEAPU8 } = getMemory(this);
|
|
1231
|
+
const { HEAPU8 } = getMemory(this, Math.max(old_path + old_path_len, new_path + new_path_len));
|
|
1199
1232
|
const fs = getFs(this);
|
|
1200
1233
|
const resolvedOldPath = await resolvePathAsync(fs, oldWrap, decoder.decode((0, util_1.unsharedSlice)(HEAPU8, old_path, old_path + old_path_len)), old_flags);
|
|
1201
1234
|
const resolvedNewPath = (0, path_1.resolve)(newWrap.realPath, decoder.decode((0, util_1.unsharedSlice)(HEAPU8, new_path, new_path + new_path_len)));
|
|
@@ -1261,12 +1294,12 @@ class WASI {
|
|
|
1261
1294
|
const { flags: flagsRes, needed_base: neededBase, needed_inheriting: neededInheriting } = pathOpen(o_flags, fs_rights_base, fs_rights_inheriting, fs_flags);
|
|
1262
1295
|
const wasi = _wasi.get(this);
|
|
1263
1296
|
const fileDescriptor = wasi.fds.get(dirfd, neededBase, neededInheriting);
|
|
1264
|
-
const memory = getMemory(this);
|
|
1297
|
+
const memory = getMemory(this, Math.max(path + path_len, fd + 4));
|
|
1265
1298
|
const HEAPU8 = memory.HEAPU8;
|
|
1266
1299
|
const pathString = decoder.decode((0, util_1.unsharedSlice)(HEAPU8, path, path + path_len));
|
|
1267
1300
|
const fs = getFs(this);
|
|
1268
1301
|
const resolved_path = resolvePathSync(fs, fileDescriptor, pathString, dirflags);
|
|
1269
|
-
const r = fs.openSync(resolved_path, flagsRes, 0o666);
|
|
1302
|
+
const r = fs.openSync(resolved_path, _isWin32Flags ? _toWinOpenFlags(flagsRes) : flagsRes, 0o666);
|
|
1270
1303
|
const filetype = wasi.fds.getFileTypeByFd(r);
|
|
1271
1304
|
if ((filetype !== types_1.WasiFileType.DIRECTORY) &&
|
|
1272
1305
|
((o_flags & types_1.WasiFileControlFlag.O_DIRECTORY) !== 0 ||
|
|
@@ -1297,12 +1330,12 @@ class WASI {
|
|
|
1297
1330
|
const { flags: flagsRes, needed_base: neededBase, needed_inheriting: neededInheriting } = pathOpen(o_flags, fs_rights_base, fs_rights_inheriting, fs_flags);
|
|
1298
1331
|
const wasi = _wasi.get(this);
|
|
1299
1332
|
const fileDescriptor = wasi.fds.get(dirfd, neededBase, neededInheriting);
|
|
1300
|
-
const memory = getMemory(this);
|
|
1333
|
+
const memory = getMemory(this, Math.max(path + path_len, fd + 4));
|
|
1301
1334
|
const HEAPU8 = memory.HEAPU8;
|
|
1302
1335
|
const pathString = decoder.decode((0, util_1.unsharedSlice)(HEAPU8, path, path + path_len));
|
|
1303
1336
|
const fs = getFs(this);
|
|
1304
1337
|
const resolved_path = await resolvePathAsync(fs, fileDescriptor, pathString, dirflags);
|
|
1305
|
-
const r = await fs.promises.open(resolved_path, flagsRes, 0o666);
|
|
1338
|
+
const r = await fs.promises.open(resolved_path, _isWin32Flags ? _toWinOpenFlags(flagsRes) : flagsRes, 0o666);
|
|
1306
1339
|
const filetype = await wasi.fds.getFileTypeByFd(r);
|
|
1307
1340
|
if ((o_flags & types_1.WasiFileControlFlag.O_DIRECTORY) !== 0 && filetype !== types_1.WasiFileType.DIRECTORY) {
|
|
1308
1341
|
return types_1.WasiErrno.ENOTDIR;
|
|
@@ -1329,7 +1362,7 @@ class WASI {
|
|
|
1329
1362
|
if (path === 0 || buf === 0 || bufused === 0) {
|
|
1330
1363
|
return types_1.WasiErrno.EINVAL;
|
|
1331
1364
|
}
|
|
1332
|
-
const { HEAPU8, view } = getMemory(this);
|
|
1365
|
+
const { HEAPU8, view } = getMemory(this, Math.max(path + path_len, buf + buf_len, bufused + 4));
|
|
1333
1366
|
const wasi = _wasi.get(this);
|
|
1334
1367
|
const fileDescriptor = wasi.fds.get(fd, types_1.WasiRights.PATH_READLINK, BigInt(0));
|
|
1335
1368
|
let pathString = decoder.decode((0, util_1.unsharedSlice)(HEAPU8, path, path + path_len));
|
|
@@ -1353,7 +1386,7 @@ class WASI {
|
|
|
1353
1386
|
if (path === 0 || buf === 0 || bufused === 0) {
|
|
1354
1387
|
return types_1.WasiErrno.EINVAL;
|
|
1355
1388
|
}
|
|
1356
|
-
const { HEAPU8, view } = getMemory(this);
|
|
1389
|
+
const { HEAPU8, view } = getMemory(this, Math.max(path + path_len, buf + buf_len, bufused + 4));
|
|
1357
1390
|
const wasi = _wasi.get(this);
|
|
1358
1391
|
const fileDescriptor = wasi.fds.get(fd, types_1.WasiRights.PATH_READLINK, BigInt(0));
|
|
1359
1392
|
let pathString = decoder.decode((0, util_1.unsharedSlice)(HEAPU8, path, path + path_len));
|
|
@@ -1375,7 +1408,7 @@ class WASI {
|
|
|
1375
1408
|
if (path === 0) {
|
|
1376
1409
|
return types_1.WasiErrno.EINVAL;
|
|
1377
1410
|
}
|
|
1378
|
-
const { HEAPU8 } = getMemory(this);
|
|
1411
|
+
const { HEAPU8 } = getMemory(this, path + path_len);
|
|
1379
1412
|
const wasi = _wasi.get(this);
|
|
1380
1413
|
const fileDescriptor = wasi.fds.get(fd, types_1.WasiRights.PATH_REMOVE_DIRECTORY, BigInt(0));
|
|
1381
1414
|
let pathString = decoder.decode((0, util_1.unsharedSlice)(HEAPU8, path, path + path_len));
|
|
@@ -1389,7 +1422,7 @@ class WASI {
|
|
|
1389
1422
|
if (path === 0) {
|
|
1390
1423
|
return types_1.WasiErrno.EINVAL;
|
|
1391
1424
|
}
|
|
1392
|
-
const { HEAPU8 } = getMemory(this);
|
|
1425
|
+
const { HEAPU8 } = getMemory(this, path + path_len);
|
|
1393
1426
|
const wasi = _wasi.get(this);
|
|
1394
1427
|
const fileDescriptor = wasi.fds.get(fd, types_1.WasiRights.PATH_REMOVE_DIRECTORY, BigInt(0));
|
|
1395
1428
|
let pathString = decoder.decode((0, util_1.unsharedSlice)(HEAPU8, path, path + path_len));
|
|
@@ -1416,7 +1449,7 @@ class WASI {
|
|
|
1416
1449
|
oldWrap = wasi.fds.get(old_fd, types_1.WasiRights.PATH_RENAME_SOURCE, BigInt(0));
|
|
1417
1450
|
newWrap = wasi.fds.get(new_fd, types_1.WasiRights.PATH_RENAME_TARGET, BigInt(0));
|
|
1418
1451
|
}
|
|
1419
|
-
const { HEAPU8 } = getMemory(this);
|
|
1452
|
+
const { HEAPU8 } = getMemory(this, Math.max(old_path + old_path_len, new_path + new_path_len));
|
|
1420
1453
|
const resolvedOldPath = (0, path_1.resolve)(oldWrap.realPath, decoder.decode((0, util_1.unsharedSlice)(HEAPU8, old_path, old_path + old_path_len)));
|
|
1421
1454
|
const resolvedNewPath = (0, path_1.resolve)(newWrap.realPath, decoder.decode((0, util_1.unsharedSlice)(HEAPU8, new_path, new_path + new_path_len)));
|
|
1422
1455
|
const fs = getFs(this);
|
|
@@ -1440,7 +1473,7 @@ class WASI {
|
|
|
1440
1473
|
oldWrap = wasi.fds.get(old_fd, types_1.WasiRights.PATH_RENAME_SOURCE, BigInt(0));
|
|
1441
1474
|
newWrap = wasi.fds.get(new_fd, types_1.WasiRights.PATH_RENAME_TARGET, BigInt(0));
|
|
1442
1475
|
}
|
|
1443
|
-
const { HEAPU8 } = getMemory(this);
|
|
1476
|
+
const { HEAPU8 } = getMemory(this, Math.max(old_path + old_path_len, new_path + new_path_len));
|
|
1444
1477
|
const resolvedOldPath = (0, path_1.resolve)(oldWrap.realPath, decoder.decode((0, util_1.unsharedSlice)(HEAPU8, old_path, old_path + old_path_len)));
|
|
1445
1478
|
const resolvedNewPath = (0, path_1.resolve)(newWrap.realPath, decoder.decode((0, util_1.unsharedSlice)(HEAPU8, new_path, new_path + new_path_len)));
|
|
1446
1479
|
const fs = getFs(this);
|
|
@@ -1455,7 +1488,7 @@ class WASI {
|
|
|
1455
1488
|
if (old_path === 0 || new_path === 0) {
|
|
1456
1489
|
return types_1.WasiErrno.EINVAL;
|
|
1457
1490
|
}
|
|
1458
|
-
const { HEAPU8 } = getMemory(this);
|
|
1491
|
+
const { HEAPU8 } = getMemory(this, Math.max(old_path + old_path_len, new_path + new_path_len));
|
|
1459
1492
|
const wasi = _wasi.get(this);
|
|
1460
1493
|
const fileDescriptor = wasi.fds.get(fd, types_1.WasiRights.PATH_SYMLINK, BigInt(0));
|
|
1461
1494
|
const oldPath = decoder.decode((0, util_1.unsharedSlice)(HEAPU8, old_path, old_path + old_path_len));
|
|
@@ -1475,7 +1508,7 @@ class WASI {
|
|
|
1475
1508
|
if (old_path === 0 || new_path === 0) {
|
|
1476
1509
|
return types_1.WasiErrno.EINVAL;
|
|
1477
1510
|
}
|
|
1478
|
-
const { HEAPU8 } = getMemory(this);
|
|
1511
|
+
const { HEAPU8 } = getMemory(this, Math.max(old_path + old_path_len, new_path + new_path_len));
|
|
1479
1512
|
const wasi = _wasi.get(this);
|
|
1480
1513
|
const fileDescriptor = wasi.fds.get(fd, types_1.WasiRights.PATH_SYMLINK, BigInt(0));
|
|
1481
1514
|
const oldPath = decoder.decode((0, util_1.unsharedSlice)(HEAPU8, old_path, old_path + old_path_len));
|
|
@@ -1491,7 +1524,7 @@ class WASI {
|
|
|
1491
1524
|
if (path === 0) {
|
|
1492
1525
|
return types_1.WasiErrno.EINVAL;
|
|
1493
1526
|
}
|
|
1494
|
-
const { HEAPU8 } = getMemory(this);
|
|
1527
|
+
const { HEAPU8 } = getMemory(this, path + path_len);
|
|
1495
1528
|
const wasi = _wasi.get(this);
|
|
1496
1529
|
const fileDescriptor = wasi.fds.get(fd, types_1.WasiRights.PATH_UNLINK_FILE, BigInt(0));
|
|
1497
1530
|
let pathString = decoder.decode((0, util_1.unsharedSlice)(HEAPU8, path, path + path_len));
|
|
@@ -1505,7 +1538,7 @@ class WASI {
|
|
|
1505
1538
|
if (path === 0) {
|
|
1506
1539
|
return types_1.WasiErrno.EINVAL;
|
|
1507
1540
|
}
|
|
1508
|
-
const { HEAPU8 } = getMemory(this);
|
|
1541
|
+
const { HEAPU8 } = getMemory(this, path + path_len);
|
|
1509
1542
|
const wasi = _wasi.get(this);
|
|
1510
1543
|
const fileDescriptor = wasi.fds.get(fd, types_1.WasiRights.PATH_UNLINK_FILE, BigInt(0));
|
|
1511
1544
|
let pathString = decoder.decode((0, util_1.unsharedSlice)(HEAPU8, path, path + path_len));
|
package/lib/mjs/wasi/path.mjs
CHANGED
|
@@ -1,6 +1,141 @@
|
|
|
1
1
|
import { validateString } from "./util.mjs";
|
|
2
2
|
const CHAR_DOT = 46; /* . */
|
|
3
3
|
const CHAR_FORWARD_SLASH = 47; /* / */
|
|
4
|
+
const CHAR_BACKWARD_SLASH = 92; /* \ */
|
|
5
|
+
const CHAR_COLON = 58; /* : */
|
|
6
|
+
const CHAR_UPPERCASE_A = 65; /* A */
|
|
7
|
+
const CHAR_UPPERCASE_Z = 90; /* Z */
|
|
8
|
+
const CHAR_LOWERCASE_A = 97; /* a */
|
|
9
|
+
const CHAR_LOWERCASE_Z = 122; /* z */
|
|
10
|
+
function isPathSeparatorWin(code) {
|
|
11
|
+
return code === CHAR_FORWARD_SLASH || code === CHAR_BACKWARD_SLASH;
|
|
12
|
+
}
|
|
13
|
+
function isWindowsDeviceRoot(code) {
|
|
14
|
+
return (code >= CHAR_UPPERCASE_A && code <= CHAR_UPPERCASE_Z) ||
|
|
15
|
+
(code >= CHAR_LOWERCASE_A && code <= CHAR_LOWERCASE_Z);
|
|
16
|
+
}
|
|
17
|
+
const _isWin32 = typeof process !== 'undefined' && process.platform === 'win32';
|
|
18
|
+
/**
|
|
19
|
+
* Windows variant of `resolve()`. Mirrors Node's `path.win32.resolve`
|
|
20
|
+
* semantics enough for the WASI shim's needs (drive-letter absolutes
|
|
21
|
+
* + UNC paths + per-drive cwd lookups via `process.env`/`process.cwd`).
|
|
22
|
+
*
|
|
23
|
+
* Why this is needed: on Windows, `FileDescriptor.realPath` is the
|
|
24
|
+
* host realpath returned by `fs.realpathSync(realPath, 'utf8')` — the
|
|
25
|
+
* backslash form `D:\…`. The POSIX-only `resolveImpl` below only
|
|
26
|
+
* treats `/` as a separator, reads `D` as non-`/`, decides realPath
|
|
27
|
+
* is "relative", and produces a garbage joined path. Downstream
|
|
28
|
+
* `fs.openSync(garbage)` then returns `EINVAL` and the WASI caller
|
|
29
|
+
* sees a permanent failure. This function gives us the correct
|
|
30
|
+
* Windows-style resolution without taking a Node-only `path` import
|
|
31
|
+
* (which would break browser bundles of this package).
|
|
32
|
+
*
|
|
33
|
+
* Cribbed from Node's `lib/path.js` `win32.resolve()` (MIT-licensed),
|
|
34
|
+
* trimmed to what WASI realpath resolution actually exercises.
|
|
35
|
+
*/
|
|
36
|
+
function resolveWin32(args) {
|
|
37
|
+
let resolvedDevice = '';
|
|
38
|
+
let resolvedTail = '';
|
|
39
|
+
let resolvedAbsolute = false;
|
|
40
|
+
for (let i = args.length - 1; i >= -1; i--) {
|
|
41
|
+
let path;
|
|
42
|
+
if (i >= 0) {
|
|
43
|
+
path = args[i];
|
|
44
|
+
validateString(path, 'path');
|
|
45
|
+
if (path.length === 0)
|
|
46
|
+
continue;
|
|
47
|
+
}
|
|
48
|
+
else if (resolvedDevice.length === 0) {
|
|
49
|
+
path = (typeof process !== 'undefined' && typeof process.cwd === 'function')
|
|
50
|
+
? process.cwd()
|
|
51
|
+
: '';
|
|
52
|
+
}
|
|
53
|
+
else {
|
|
54
|
+
// Look up per-drive cwd via the `=X:` env var convention; fall back
|
|
55
|
+
// to the global cwd if absent.
|
|
56
|
+
const envKey = `=${resolvedDevice}`;
|
|
57
|
+
const env = (typeof process !== 'undefined') ? process.env : undefined;
|
|
58
|
+
path = (env && typeof env[envKey] === 'string')
|
|
59
|
+
? env[envKey]
|
|
60
|
+
: (typeof process !== 'undefined' && typeof process.cwd === 'function')
|
|
61
|
+
? process.cwd()
|
|
62
|
+
: '';
|
|
63
|
+
if (path === undefined ||
|
|
64
|
+
(path.slice(0, 2).toLowerCase() !== resolvedDevice.toLowerCase() &&
|
|
65
|
+
path.charCodeAt(2) === CHAR_BACKWARD_SLASH)) {
|
|
66
|
+
path = `${resolvedDevice}\\`;
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
const len = path.length;
|
|
70
|
+
let rootEnd = 0;
|
|
71
|
+
let device = '';
|
|
72
|
+
let isAbsolute = false;
|
|
73
|
+
const code = path.charCodeAt(0);
|
|
74
|
+
if (len === 1) {
|
|
75
|
+
if (isPathSeparatorWin(code)) {
|
|
76
|
+
rootEnd = 1;
|
|
77
|
+
isAbsolute = true;
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
else if (isPathSeparatorWin(code)) {
|
|
81
|
+
isAbsolute = true;
|
|
82
|
+
if (isPathSeparatorWin(path.charCodeAt(1))) {
|
|
83
|
+
// UNC path: `\\server\share\…`
|
|
84
|
+
let j = 2;
|
|
85
|
+
let last = j;
|
|
86
|
+
while (j < len && !isPathSeparatorWin(path.charCodeAt(j)))
|
|
87
|
+
j++;
|
|
88
|
+
if (j < len && j !== last) {
|
|
89
|
+
const firstPart = path.slice(last, j);
|
|
90
|
+
last = j;
|
|
91
|
+
while (j < len && isPathSeparatorWin(path.charCodeAt(j)))
|
|
92
|
+
j++;
|
|
93
|
+
if (j < len && j !== last) {
|
|
94
|
+
last = j;
|
|
95
|
+
while (j < len && !isPathSeparatorWin(path.charCodeAt(j)))
|
|
96
|
+
j++;
|
|
97
|
+
if (j === len || j !== last) {
|
|
98
|
+
device = `\\\\${firstPart}\\${path.slice(last, j)}`;
|
|
99
|
+
rootEnd = j;
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
else {
|
|
105
|
+
rootEnd = 1;
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
else if (isWindowsDeviceRoot(code) && path.charCodeAt(1) === CHAR_COLON) {
|
|
109
|
+
device = path.slice(0, 2);
|
|
110
|
+
rootEnd = 2;
|
|
111
|
+
if (len > 2 && isPathSeparatorWin(path.charCodeAt(2))) {
|
|
112
|
+
isAbsolute = true;
|
|
113
|
+
rootEnd = 3;
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
if (device.length > 0) {
|
|
117
|
+
if (resolvedDevice.length > 0) {
|
|
118
|
+
if (device.toLowerCase() !== resolvedDevice.toLowerCase())
|
|
119
|
+
continue;
|
|
120
|
+
}
|
|
121
|
+
else {
|
|
122
|
+
resolvedDevice = device;
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
if (resolvedAbsolute) {
|
|
126
|
+
if (resolvedDevice.length > 0)
|
|
127
|
+
break;
|
|
128
|
+
}
|
|
129
|
+
else {
|
|
130
|
+
resolvedTail = `${path.slice(rootEnd)}\\${resolvedTail}`;
|
|
131
|
+
resolvedAbsolute = isAbsolute;
|
|
132
|
+
if (isAbsolute && resolvedDevice.length > 0)
|
|
133
|
+
break;
|
|
134
|
+
}
|
|
135
|
+
}
|
|
136
|
+
resolvedTail = normalizeString(resolvedTail, !resolvedAbsolute, '\\', isPathSeparatorWin);
|
|
137
|
+
return resolvedDevice + (resolvedAbsolute ? '\\' : '') + resolvedTail || '.';
|
|
138
|
+
}
|
|
4
139
|
function isPosixPathSeparator(code) {
|
|
5
140
|
return code === CHAR_FORWARD_SLASH;
|
|
6
141
|
}
|
|
@@ -78,6 +213,13 @@ function normalizeString(path, allowAboveRoot, separator, isPathSeparator) {
|
|
|
78
213
|
return res;
|
|
79
214
|
}
|
|
80
215
|
export function resolve(...args) {
|
|
216
|
+
// On Windows, host paths are `D:\…` style. The POSIX-only resolver
|
|
217
|
+
// below treats `D` as a non-`/` character and produces garbage; route
|
|
218
|
+
// to the Windows-aware variant. POSIX hosts (Linux/macOS/browser)
|
|
219
|
+
// run the original code path unchanged — `_isWin32` is constant-folded
|
|
220
|
+
// away on those targets.
|
|
221
|
+
if (_isWin32)
|
|
222
|
+
return resolveWin32(args);
|
|
81
223
|
let resolvedPath = '';
|
|
82
224
|
let resolvedAbsolute = false;
|
|
83
225
|
for (let i = args.length - 1; i >= -1 && !resolvedAbsolute; i--) {
|