@tybys/wasm-util 0.10.0 → 0.10.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.
- package/dist/wasm-util.esm-bundler.js +196 -17
- package/dist/wasm-util.esm.js +196 -17
- package/dist/wasm-util.esm.min.js +1 -1
- package/dist/wasm-util.js +196 -17
- package/dist/wasm-util.min.js +1 -1
- package/lib/cjs/wasi/path.js +142 -0
- package/lib/cjs/wasi/preview1.js +54 -17
- package/lib/mjs/wasi/path.mjs +142 -0
- package/lib/mjs/wasi/preview1.mjs +54 -17
- package/package.json +1 -1
|
@@ -306,6 +306,141 @@ function asyncifyLoadSync(asyncify, buffer, imports) {
|
|
|
306
306
|
|
|
307
307
|
const CHAR_DOT = 46; /* . */
|
|
308
308
|
const CHAR_FORWARD_SLASH = 47; /* / */
|
|
309
|
+
const CHAR_BACKWARD_SLASH = 92; /* \ */
|
|
310
|
+
const CHAR_COLON = 58; /* : */
|
|
311
|
+
const CHAR_UPPERCASE_A = 65; /* A */
|
|
312
|
+
const CHAR_UPPERCASE_Z = 90; /* Z */
|
|
313
|
+
const CHAR_LOWERCASE_A = 97; /* a */
|
|
314
|
+
const CHAR_LOWERCASE_Z = 122; /* z */
|
|
315
|
+
function isPathSeparatorWin(code) {
|
|
316
|
+
return code === CHAR_FORWARD_SLASH || code === CHAR_BACKWARD_SLASH;
|
|
317
|
+
}
|
|
318
|
+
function isWindowsDeviceRoot(code) {
|
|
319
|
+
return (code >= CHAR_UPPERCASE_A && code <= CHAR_UPPERCASE_Z) ||
|
|
320
|
+
(code >= CHAR_LOWERCASE_A && code <= CHAR_LOWERCASE_Z);
|
|
321
|
+
}
|
|
322
|
+
const _isWin32 = typeof process !== 'undefined' && process.platform === 'win32';
|
|
323
|
+
/**
|
|
324
|
+
* Windows variant of `resolve()`. Mirrors Node's `path.win32.resolve`
|
|
325
|
+
* semantics enough for the WASI shim's needs (drive-letter absolutes
|
|
326
|
+
* + UNC paths + per-drive cwd lookups via `process.env`/`process.cwd`).
|
|
327
|
+
*
|
|
328
|
+
* Why this is needed: on Windows, `FileDescriptor.realPath` is the
|
|
329
|
+
* host realpath returned by `fs.realpathSync(realPath, 'utf8')` — the
|
|
330
|
+
* backslash form `D:\…`. The POSIX-only `resolveImpl` below only
|
|
331
|
+
* treats `/` as a separator, reads `D` as non-`/`, decides realPath
|
|
332
|
+
* is "relative", and produces a garbage joined path. Downstream
|
|
333
|
+
* `fs.openSync(garbage)` then returns `EINVAL` and the WASI caller
|
|
334
|
+
* sees a permanent failure. This function gives us the correct
|
|
335
|
+
* Windows-style resolution without taking a Node-only `path` import
|
|
336
|
+
* (which would break browser bundles of this package).
|
|
337
|
+
*
|
|
338
|
+
* Cribbed from Node's `lib/path.js` `win32.resolve()` (MIT-licensed),
|
|
339
|
+
* trimmed to what WASI realpath resolution actually exercises.
|
|
340
|
+
*/
|
|
341
|
+
function resolveWin32(args) {
|
|
342
|
+
let resolvedDevice = '';
|
|
343
|
+
let resolvedTail = '';
|
|
344
|
+
let resolvedAbsolute = false;
|
|
345
|
+
for (let i = args.length - 1; i >= -1; i--) {
|
|
346
|
+
let path;
|
|
347
|
+
if (i >= 0) {
|
|
348
|
+
path = args[i];
|
|
349
|
+
validateString(path, 'path');
|
|
350
|
+
if (path.length === 0)
|
|
351
|
+
continue;
|
|
352
|
+
}
|
|
353
|
+
else if (resolvedDevice.length === 0) {
|
|
354
|
+
path = (typeof process !== 'undefined' && typeof process.cwd === 'function')
|
|
355
|
+
? process.cwd()
|
|
356
|
+
: '';
|
|
357
|
+
}
|
|
358
|
+
else {
|
|
359
|
+
// Look up per-drive cwd via the `=X:` env var convention; fall back
|
|
360
|
+
// to the global cwd if absent.
|
|
361
|
+
const envKey = `=${resolvedDevice}`;
|
|
362
|
+
const env = (typeof process !== 'undefined') ? process.env : undefined;
|
|
363
|
+
path = (env && typeof env[envKey] === 'string')
|
|
364
|
+
? env[envKey]
|
|
365
|
+
: (typeof process !== 'undefined' && typeof process.cwd === 'function')
|
|
366
|
+
? process.cwd()
|
|
367
|
+
: '';
|
|
368
|
+
if (path === undefined ||
|
|
369
|
+
(path.slice(0, 2).toLowerCase() !== resolvedDevice.toLowerCase() &&
|
|
370
|
+
path.charCodeAt(2) === CHAR_BACKWARD_SLASH)) {
|
|
371
|
+
path = `${resolvedDevice}\\`;
|
|
372
|
+
}
|
|
373
|
+
}
|
|
374
|
+
const len = path.length;
|
|
375
|
+
let rootEnd = 0;
|
|
376
|
+
let device = '';
|
|
377
|
+
let isAbsolute = false;
|
|
378
|
+
const code = path.charCodeAt(0);
|
|
379
|
+
if (len === 1) {
|
|
380
|
+
if (isPathSeparatorWin(code)) {
|
|
381
|
+
rootEnd = 1;
|
|
382
|
+
isAbsolute = true;
|
|
383
|
+
}
|
|
384
|
+
}
|
|
385
|
+
else if (isPathSeparatorWin(code)) {
|
|
386
|
+
isAbsolute = true;
|
|
387
|
+
if (isPathSeparatorWin(path.charCodeAt(1))) {
|
|
388
|
+
// UNC path: `\\server\share\…`
|
|
389
|
+
let j = 2;
|
|
390
|
+
let last = j;
|
|
391
|
+
while (j < len && !isPathSeparatorWin(path.charCodeAt(j)))
|
|
392
|
+
j++;
|
|
393
|
+
if (j < len && j !== last) {
|
|
394
|
+
const firstPart = path.slice(last, j);
|
|
395
|
+
last = j;
|
|
396
|
+
while (j < len && isPathSeparatorWin(path.charCodeAt(j)))
|
|
397
|
+
j++;
|
|
398
|
+
if (j < len && j !== last) {
|
|
399
|
+
last = j;
|
|
400
|
+
while (j < len && !isPathSeparatorWin(path.charCodeAt(j)))
|
|
401
|
+
j++;
|
|
402
|
+
if (j === len || j !== last) {
|
|
403
|
+
device = `\\\\${firstPart}\\${path.slice(last, j)}`;
|
|
404
|
+
rootEnd = j;
|
|
405
|
+
}
|
|
406
|
+
}
|
|
407
|
+
}
|
|
408
|
+
}
|
|
409
|
+
else {
|
|
410
|
+
rootEnd = 1;
|
|
411
|
+
}
|
|
412
|
+
}
|
|
413
|
+
else if (isWindowsDeviceRoot(code) && path.charCodeAt(1) === CHAR_COLON) {
|
|
414
|
+
device = path.slice(0, 2);
|
|
415
|
+
rootEnd = 2;
|
|
416
|
+
if (len > 2 && isPathSeparatorWin(path.charCodeAt(2))) {
|
|
417
|
+
isAbsolute = true;
|
|
418
|
+
rootEnd = 3;
|
|
419
|
+
}
|
|
420
|
+
}
|
|
421
|
+
if (device.length > 0) {
|
|
422
|
+
if (resolvedDevice.length > 0) {
|
|
423
|
+
if (device.toLowerCase() !== resolvedDevice.toLowerCase())
|
|
424
|
+
continue;
|
|
425
|
+
}
|
|
426
|
+
else {
|
|
427
|
+
resolvedDevice = device;
|
|
428
|
+
}
|
|
429
|
+
}
|
|
430
|
+
if (resolvedAbsolute) {
|
|
431
|
+
if (resolvedDevice.length > 0)
|
|
432
|
+
break;
|
|
433
|
+
}
|
|
434
|
+
else {
|
|
435
|
+
resolvedTail = `${path.slice(rootEnd)}\\${resolvedTail}`;
|
|
436
|
+
resolvedAbsolute = isAbsolute;
|
|
437
|
+
if (isAbsolute && resolvedDevice.length > 0)
|
|
438
|
+
break;
|
|
439
|
+
}
|
|
440
|
+
}
|
|
441
|
+
resolvedTail = normalizeString(resolvedTail, !resolvedAbsolute, '\\', isPathSeparatorWin);
|
|
442
|
+
return resolvedDevice + (resolvedAbsolute ? '\\' : '') + resolvedTail || '.';
|
|
443
|
+
}
|
|
309
444
|
function isPosixPathSeparator(code) {
|
|
310
445
|
return code === CHAR_FORWARD_SLASH;
|
|
311
446
|
}
|
|
@@ -381,6 +516,13 @@ function normalizeString(path, allowAboveRoot, separator, isPathSeparator) {
|
|
|
381
516
|
return res;
|
|
382
517
|
}
|
|
383
518
|
function resolve(...args) {
|
|
519
|
+
// On Windows, host paths are `D:\…` style. The POSIX-only resolver
|
|
520
|
+
// below treats `D` as a non-`/` character and produces garbage; route
|
|
521
|
+
// to the Windows-aware variant. POSIX hosts (Linux/macOS/browser)
|
|
522
|
+
// run the original code path unchanged — `_isWin32` is constant-folded
|
|
523
|
+
// away on those targets.
|
|
524
|
+
if (_isWin32)
|
|
525
|
+
return resolveWin32(args);
|
|
384
526
|
let resolvedPath = '';
|
|
385
527
|
let resolvedAbsolute = false;
|
|
386
528
|
for (let i = args.length - 1; i >= -1 && !resolvedAbsolute; i--) {
|
|
@@ -1017,6 +1159,26 @@ function wrapExports(exports, needWrap) {
|
|
|
1017
1159
|
});
|
|
1018
1160
|
}
|
|
1019
1161
|
|
|
1162
|
+
// Linux fcntl flag bits ↔ Windows libuv flag bits. `pathOpen()` builds
|
|
1163
|
+
// `flagsRes` using Linux constants (O_CREAT=0x40, O_EXCL=0x80,
|
|
1164
|
+
// O_APPEND=0x400). Windows libuv expects different bits (O_CREAT=0x100,
|
|
1165
|
+
// O_EXCL=0x400, O_APPEND=0x8). Without translation,
|
|
1166
|
+
// `fs.openSync(path, 0x241 /* L:WRONLY|CREAT|TRUNC */)` is rejected
|
|
1167
|
+
// with EINVAL because Linux's 0x40 happens to mean O_TEMPORARY on
|
|
1168
|
+
// Windows — and O_TEMPORARY without O_CREAT is invalid.
|
|
1169
|
+
const _isWin32Flags = typeof process !== 'undefined' && process.platform === 'win32';
|
|
1170
|
+
function _toWinOpenFlags(f) {
|
|
1171
|
+
let r = f & 3; // RDONLY/WRONLY/RDWR — same on both
|
|
1172
|
+
if ((f & 0x40) !== 0)
|
|
1173
|
+
r |= 0x100; // O_CREAT: Linux 0x40 -> Windows 0x100
|
|
1174
|
+
if ((f & 0x80) !== 0)
|
|
1175
|
+
r |= 0x400; // O_EXCL: Linux 0x80 -> Windows 0x400
|
|
1176
|
+
if ((f & 0x200) !== 0)
|
|
1177
|
+
r |= 0x200; // O_TRUNC: same value on both
|
|
1178
|
+
if ((f & 0x400) !== 0)
|
|
1179
|
+
r |= 0x8; // O_APPEND: Linux 0x400 -> Windows 0x8
|
|
1180
|
+
return r;
|
|
1181
|
+
}
|
|
1020
1182
|
function copyMemory(targets, src) {
|
|
1021
1183
|
if (targets.length === 0 || src.length === 0)
|
|
1022
1184
|
return 0;
|
|
@@ -1075,26 +1237,43 @@ function defineName(name, f) {
|
|
|
1075
1237
|
Object.defineProperty(f, 'name', { value: name });
|
|
1076
1238
|
return f;
|
|
1077
1239
|
}
|
|
1240
|
+
function tryCall(f, wasi, args) {
|
|
1241
|
+
let r;
|
|
1242
|
+
try {
|
|
1243
|
+
r = f.apply(wasi, args);
|
|
1244
|
+
}
|
|
1245
|
+
catch (err) {
|
|
1246
|
+
return handleError(err);
|
|
1247
|
+
}
|
|
1248
|
+
if (isPromiseLike(r)) {
|
|
1249
|
+
return r.then(_ => _, handleError);
|
|
1250
|
+
}
|
|
1251
|
+
return r;
|
|
1252
|
+
}
|
|
1078
1253
|
function syscallWrap(self, name, f) {
|
|
1079
|
-
|
|
1080
|
-
|
|
1254
|
+
let debug = false;
|
|
1255
|
+
const NODE_DEBUG_NATIVE = (() => {
|
|
1256
|
+
try {
|
|
1257
|
+
return process.env.NODE_DEBUG_NATIVE;
|
|
1258
|
+
}
|
|
1259
|
+
catch (_) {
|
|
1260
|
+
return undefined;
|
|
1261
|
+
}
|
|
1262
|
+
})();
|
|
1263
|
+
if (typeof NODE_DEBUG_NATIVE === 'string' && NODE_DEBUG_NATIVE.split(',').includes('wasi')) {
|
|
1264
|
+
debug = true;
|
|
1265
|
+
}
|
|
1266
|
+
return debug
|
|
1267
|
+
? defineName(name, function () {
|
|
1081
1268
|
const args = Array.prototype.slice.call(arguments);
|
|
1082
1269
|
let debugArgs = [`${name}(${Array.from({ length: arguments.length }).map(() => '%d').join(', ')})`];
|
|
1083
1270
|
debugArgs = debugArgs.concat(args);
|
|
1084
1271
|
console.debug.apply(console, debugArgs);
|
|
1085
|
-
|
|
1086
|
-
|
|
1087
|
-
|
|
1088
|
-
|
|
1089
|
-
}
|
|
1090
|
-
catch (err) {
|
|
1091
|
-
return handleError(err);
|
|
1092
|
-
}
|
|
1093
|
-
if (isPromiseLike(r)) {
|
|
1094
|
-
return r.then(_ => _, handleError);
|
|
1095
|
-
}
|
|
1096
|
-
return r;
|
|
1097
|
-
});
|
|
1272
|
+
return tryCall(f, self, args);
|
|
1273
|
+
})
|
|
1274
|
+
: defineName(name, function () {
|
|
1275
|
+
return tryCall(f, self, arguments);
|
|
1276
|
+
});
|
|
1098
1277
|
}
|
|
1099
1278
|
function resolvePathSync(fs, fileDescriptor, path, flags) {
|
|
1100
1279
|
let resolvedPath = resolve(fileDescriptor.realPath, path);
|
|
@@ -2256,7 +2435,7 @@ class WASI$1 {
|
|
|
2256
2435
|
const pathString = decoder.decode(unsharedSlice(HEAPU8, path, path + path_len));
|
|
2257
2436
|
const fs = getFs(this);
|
|
2258
2437
|
const resolved_path = resolvePathSync(fs, fileDescriptor, pathString, dirflags);
|
|
2259
|
-
const r = fs.openSync(resolved_path, flagsRes, 0o666);
|
|
2438
|
+
const r = fs.openSync(resolved_path, _isWin32Flags ? _toWinOpenFlags(flagsRes) : flagsRes, 0o666);
|
|
2260
2439
|
const filetype = wasi.fds.getFileTypeByFd(r);
|
|
2261
2440
|
if ((filetype !== 3 /* WasiFileType.DIRECTORY */) &&
|
|
2262
2441
|
((o_flags & 2 /* WasiFileControlFlag.O_DIRECTORY */) !== 0 ||
|
|
@@ -2292,7 +2471,7 @@ class WASI$1 {
|
|
|
2292
2471
|
const pathString = decoder.decode(unsharedSlice(HEAPU8, path, path + path_len));
|
|
2293
2472
|
const fs = getFs(this);
|
|
2294
2473
|
const resolved_path = await resolvePathAsync(fs, fileDescriptor, pathString, dirflags);
|
|
2295
|
-
const r = await fs.promises.open(resolved_path, flagsRes, 0o666);
|
|
2474
|
+
const r = await fs.promises.open(resolved_path, _isWin32Flags ? _toWinOpenFlags(flagsRes) : flagsRes, 0o666);
|
|
2296
2475
|
const filetype = await wasi.fds.getFileTypeByFd(r);
|
|
2297
2476
|
if ((o_flags & 2 /* WasiFileControlFlag.O_DIRECTORY */) !== 0 && filetype !== 3 /* WasiFileType.DIRECTORY */) {
|
|
2298
2477
|
return 54 /* WasiErrno.ENOTDIR */;
|
package/dist/wasm-util.esm.js
CHANGED
|
@@ -306,6 +306,141 @@ function asyncifyLoadSync(asyncify, buffer, imports) {
|
|
|
306
306
|
|
|
307
307
|
const CHAR_DOT = 46; /* . */
|
|
308
308
|
const CHAR_FORWARD_SLASH = 47; /* / */
|
|
309
|
+
const CHAR_BACKWARD_SLASH = 92; /* \ */
|
|
310
|
+
const CHAR_COLON = 58; /* : */
|
|
311
|
+
const CHAR_UPPERCASE_A = 65; /* A */
|
|
312
|
+
const CHAR_UPPERCASE_Z = 90; /* Z */
|
|
313
|
+
const CHAR_LOWERCASE_A = 97; /* a */
|
|
314
|
+
const CHAR_LOWERCASE_Z = 122; /* z */
|
|
315
|
+
function isPathSeparatorWin(code) {
|
|
316
|
+
return code === CHAR_FORWARD_SLASH || code === CHAR_BACKWARD_SLASH;
|
|
317
|
+
}
|
|
318
|
+
function isWindowsDeviceRoot(code) {
|
|
319
|
+
return (code >= CHAR_UPPERCASE_A && code <= CHAR_UPPERCASE_Z) ||
|
|
320
|
+
(code >= CHAR_LOWERCASE_A && code <= CHAR_LOWERCASE_Z);
|
|
321
|
+
}
|
|
322
|
+
const _isWin32 = typeof process !== 'undefined' && process.platform === 'win32';
|
|
323
|
+
/**
|
|
324
|
+
* Windows variant of `resolve()`. Mirrors Node's `path.win32.resolve`
|
|
325
|
+
* semantics enough for the WASI shim's needs (drive-letter absolutes
|
|
326
|
+
* + UNC paths + per-drive cwd lookups via `process.env`/`process.cwd`).
|
|
327
|
+
*
|
|
328
|
+
* Why this is needed: on Windows, `FileDescriptor.realPath` is the
|
|
329
|
+
* host realpath returned by `fs.realpathSync(realPath, 'utf8')` — the
|
|
330
|
+
* backslash form `D:\…`. The POSIX-only `resolveImpl` below only
|
|
331
|
+
* treats `/` as a separator, reads `D` as non-`/`, decides realPath
|
|
332
|
+
* is "relative", and produces a garbage joined path. Downstream
|
|
333
|
+
* `fs.openSync(garbage)` then returns `EINVAL` and the WASI caller
|
|
334
|
+
* sees a permanent failure. This function gives us the correct
|
|
335
|
+
* Windows-style resolution without taking a Node-only `path` import
|
|
336
|
+
* (which would break browser bundles of this package).
|
|
337
|
+
*
|
|
338
|
+
* Cribbed from Node's `lib/path.js` `win32.resolve()` (MIT-licensed),
|
|
339
|
+
* trimmed to what WASI realpath resolution actually exercises.
|
|
340
|
+
*/
|
|
341
|
+
function resolveWin32(args) {
|
|
342
|
+
let resolvedDevice = '';
|
|
343
|
+
let resolvedTail = '';
|
|
344
|
+
let resolvedAbsolute = false;
|
|
345
|
+
for (let i = args.length - 1; i >= -1; i--) {
|
|
346
|
+
let path;
|
|
347
|
+
if (i >= 0) {
|
|
348
|
+
path = args[i];
|
|
349
|
+
validateString(path, 'path');
|
|
350
|
+
if (path.length === 0)
|
|
351
|
+
continue;
|
|
352
|
+
}
|
|
353
|
+
else if (resolvedDevice.length === 0) {
|
|
354
|
+
path = (typeof process !== 'undefined' && typeof process.cwd === 'function')
|
|
355
|
+
? process.cwd()
|
|
356
|
+
: '';
|
|
357
|
+
}
|
|
358
|
+
else {
|
|
359
|
+
// Look up per-drive cwd via the `=X:` env var convention; fall back
|
|
360
|
+
// to the global cwd if absent.
|
|
361
|
+
const envKey = `=${resolvedDevice}`;
|
|
362
|
+
const env = (typeof process !== 'undefined') ? process.env : undefined;
|
|
363
|
+
path = (env && typeof env[envKey] === 'string')
|
|
364
|
+
? env[envKey]
|
|
365
|
+
: (typeof process !== 'undefined' && typeof process.cwd === 'function')
|
|
366
|
+
? process.cwd()
|
|
367
|
+
: '';
|
|
368
|
+
if (path === undefined ||
|
|
369
|
+
(path.slice(0, 2).toLowerCase() !== resolvedDevice.toLowerCase() &&
|
|
370
|
+
path.charCodeAt(2) === CHAR_BACKWARD_SLASH)) {
|
|
371
|
+
path = `${resolvedDevice}\\`;
|
|
372
|
+
}
|
|
373
|
+
}
|
|
374
|
+
const len = path.length;
|
|
375
|
+
let rootEnd = 0;
|
|
376
|
+
let device = '';
|
|
377
|
+
let isAbsolute = false;
|
|
378
|
+
const code = path.charCodeAt(0);
|
|
379
|
+
if (len === 1) {
|
|
380
|
+
if (isPathSeparatorWin(code)) {
|
|
381
|
+
rootEnd = 1;
|
|
382
|
+
isAbsolute = true;
|
|
383
|
+
}
|
|
384
|
+
}
|
|
385
|
+
else if (isPathSeparatorWin(code)) {
|
|
386
|
+
isAbsolute = true;
|
|
387
|
+
if (isPathSeparatorWin(path.charCodeAt(1))) {
|
|
388
|
+
// UNC path: `\\server\share\…`
|
|
389
|
+
let j = 2;
|
|
390
|
+
let last = j;
|
|
391
|
+
while (j < len && !isPathSeparatorWin(path.charCodeAt(j)))
|
|
392
|
+
j++;
|
|
393
|
+
if (j < len && j !== last) {
|
|
394
|
+
const firstPart = path.slice(last, j);
|
|
395
|
+
last = j;
|
|
396
|
+
while (j < len && isPathSeparatorWin(path.charCodeAt(j)))
|
|
397
|
+
j++;
|
|
398
|
+
if (j < len && j !== last) {
|
|
399
|
+
last = j;
|
|
400
|
+
while (j < len && !isPathSeparatorWin(path.charCodeAt(j)))
|
|
401
|
+
j++;
|
|
402
|
+
if (j === len || j !== last) {
|
|
403
|
+
device = `\\\\${firstPart}\\${path.slice(last, j)}`;
|
|
404
|
+
rootEnd = j;
|
|
405
|
+
}
|
|
406
|
+
}
|
|
407
|
+
}
|
|
408
|
+
}
|
|
409
|
+
else {
|
|
410
|
+
rootEnd = 1;
|
|
411
|
+
}
|
|
412
|
+
}
|
|
413
|
+
else if (isWindowsDeviceRoot(code) && path.charCodeAt(1) === CHAR_COLON) {
|
|
414
|
+
device = path.slice(0, 2);
|
|
415
|
+
rootEnd = 2;
|
|
416
|
+
if (len > 2 && isPathSeparatorWin(path.charCodeAt(2))) {
|
|
417
|
+
isAbsolute = true;
|
|
418
|
+
rootEnd = 3;
|
|
419
|
+
}
|
|
420
|
+
}
|
|
421
|
+
if (device.length > 0) {
|
|
422
|
+
if (resolvedDevice.length > 0) {
|
|
423
|
+
if (device.toLowerCase() !== resolvedDevice.toLowerCase())
|
|
424
|
+
continue;
|
|
425
|
+
}
|
|
426
|
+
else {
|
|
427
|
+
resolvedDevice = device;
|
|
428
|
+
}
|
|
429
|
+
}
|
|
430
|
+
if (resolvedAbsolute) {
|
|
431
|
+
if (resolvedDevice.length > 0)
|
|
432
|
+
break;
|
|
433
|
+
}
|
|
434
|
+
else {
|
|
435
|
+
resolvedTail = `${path.slice(rootEnd)}\\${resolvedTail}`;
|
|
436
|
+
resolvedAbsolute = isAbsolute;
|
|
437
|
+
if (isAbsolute && resolvedDevice.length > 0)
|
|
438
|
+
break;
|
|
439
|
+
}
|
|
440
|
+
}
|
|
441
|
+
resolvedTail = normalizeString(resolvedTail, !resolvedAbsolute, '\\', isPathSeparatorWin);
|
|
442
|
+
return resolvedDevice + (resolvedAbsolute ? '\\' : '') + resolvedTail || '.';
|
|
443
|
+
}
|
|
309
444
|
function isPosixPathSeparator(code) {
|
|
310
445
|
return code === CHAR_FORWARD_SLASH;
|
|
311
446
|
}
|
|
@@ -381,6 +516,13 @@ function normalizeString(path, allowAboveRoot, separator, isPathSeparator) {
|
|
|
381
516
|
return res;
|
|
382
517
|
}
|
|
383
518
|
function resolve(...args) {
|
|
519
|
+
// On Windows, host paths are `D:\…` style. The POSIX-only resolver
|
|
520
|
+
// below treats `D` as a non-`/` character and produces garbage; route
|
|
521
|
+
// to the Windows-aware variant. POSIX hosts (Linux/macOS/browser)
|
|
522
|
+
// run the original code path unchanged — `_isWin32` is constant-folded
|
|
523
|
+
// away on those targets.
|
|
524
|
+
if (_isWin32)
|
|
525
|
+
return resolveWin32(args);
|
|
384
526
|
let resolvedPath = '';
|
|
385
527
|
let resolvedAbsolute = false;
|
|
386
528
|
for (let i = args.length - 1; i >= -1 && !resolvedAbsolute; i--) {
|
|
@@ -1017,6 +1159,26 @@ function wrapExports(exports, needWrap) {
|
|
|
1017
1159
|
});
|
|
1018
1160
|
}
|
|
1019
1161
|
|
|
1162
|
+
// Linux fcntl flag bits ↔ Windows libuv flag bits. `pathOpen()` builds
|
|
1163
|
+
// `flagsRes` using Linux constants (O_CREAT=0x40, O_EXCL=0x80,
|
|
1164
|
+
// O_APPEND=0x400). Windows libuv expects different bits (O_CREAT=0x100,
|
|
1165
|
+
// O_EXCL=0x400, O_APPEND=0x8). Without translation,
|
|
1166
|
+
// `fs.openSync(path, 0x241 /* L:WRONLY|CREAT|TRUNC */)` is rejected
|
|
1167
|
+
// with EINVAL because Linux's 0x40 happens to mean O_TEMPORARY on
|
|
1168
|
+
// Windows — and O_TEMPORARY without O_CREAT is invalid.
|
|
1169
|
+
const _isWin32Flags = typeof process !== 'undefined' && process.platform === 'win32';
|
|
1170
|
+
function _toWinOpenFlags(f) {
|
|
1171
|
+
let r = f & 3; // RDONLY/WRONLY/RDWR — same on both
|
|
1172
|
+
if ((f & 0x40) !== 0)
|
|
1173
|
+
r |= 0x100; // O_CREAT: Linux 0x40 -> Windows 0x100
|
|
1174
|
+
if ((f & 0x80) !== 0)
|
|
1175
|
+
r |= 0x400; // O_EXCL: Linux 0x80 -> Windows 0x400
|
|
1176
|
+
if ((f & 0x200) !== 0)
|
|
1177
|
+
r |= 0x200; // O_TRUNC: same value on both
|
|
1178
|
+
if ((f & 0x400) !== 0)
|
|
1179
|
+
r |= 0x8; // O_APPEND: Linux 0x400 -> Windows 0x8
|
|
1180
|
+
return r;
|
|
1181
|
+
}
|
|
1020
1182
|
function copyMemory(targets, src) {
|
|
1021
1183
|
if (targets.length === 0 || src.length === 0)
|
|
1022
1184
|
return 0;
|
|
@@ -1075,26 +1237,43 @@ function defineName(name, f) {
|
|
|
1075
1237
|
Object.defineProperty(f, 'name', { value: name });
|
|
1076
1238
|
return f;
|
|
1077
1239
|
}
|
|
1240
|
+
function tryCall(f, wasi, args) {
|
|
1241
|
+
let r;
|
|
1242
|
+
try {
|
|
1243
|
+
r = f.apply(wasi, args);
|
|
1244
|
+
}
|
|
1245
|
+
catch (err) {
|
|
1246
|
+
return handleError(err);
|
|
1247
|
+
}
|
|
1248
|
+
if (isPromiseLike(r)) {
|
|
1249
|
+
return r.then(_ => _, handleError);
|
|
1250
|
+
}
|
|
1251
|
+
return r;
|
|
1252
|
+
}
|
|
1078
1253
|
function syscallWrap(self, name, f) {
|
|
1079
|
-
|
|
1080
|
-
|
|
1254
|
+
let debug = false;
|
|
1255
|
+
const NODE_DEBUG_NATIVE = (() => {
|
|
1256
|
+
try {
|
|
1257
|
+
return "wasi";
|
|
1258
|
+
}
|
|
1259
|
+
catch (_) {
|
|
1260
|
+
return undefined;
|
|
1261
|
+
}
|
|
1262
|
+
})();
|
|
1263
|
+
if (typeof NODE_DEBUG_NATIVE === 'string' && NODE_DEBUG_NATIVE.split(',').includes('wasi')) {
|
|
1264
|
+
debug = true;
|
|
1265
|
+
}
|
|
1266
|
+
return debug
|
|
1267
|
+
? defineName(name, function () {
|
|
1081
1268
|
const args = Array.prototype.slice.call(arguments);
|
|
1082
1269
|
let debugArgs = [`${name}(${Array.from({ length: arguments.length }).map(() => '%d').join(', ')})`];
|
|
1083
1270
|
debugArgs = debugArgs.concat(args);
|
|
1084
1271
|
console.debug.apply(console, debugArgs);
|
|
1085
|
-
|
|
1086
|
-
|
|
1087
|
-
|
|
1088
|
-
|
|
1089
|
-
}
|
|
1090
|
-
catch (err) {
|
|
1091
|
-
return handleError(err);
|
|
1092
|
-
}
|
|
1093
|
-
if (isPromiseLike(r)) {
|
|
1094
|
-
return r.then(_ => _, handleError);
|
|
1095
|
-
}
|
|
1096
|
-
return r;
|
|
1097
|
-
});
|
|
1272
|
+
return tryCall(f, self, args);
|
|
1273
|
+
})
|
|
1274
|
+
: defineName(name, function () {
|
|
1275
|
+
return tryCall(f, self, arguments);
|
|
1276
|
+
});
|
|
1098
1277
|
}
|
|
1099
1278
|
function resolvePathSync(fs, fileDescriptor, path, flags) {
|
|
1100
1279
|
let resolvedPath = resolve(fileDescriptor.realPath, path);
|
|
@@ -2256,7 +2435,7 @@ class WASI$1 {
|
|
|
2256
2435
|
const pathString = decoder.decode(unsharedSlice(HEAPU8, path, path + path_len));
|
|
2257
2436
|
const fs = getFs(this);
|
|
2258
2437
|
const resolved_path = resolvePathSync(fs, fileDescriptor, pathString, dirflags);
|
|
2259
|
-
const r = fs.openSync(resolved_path, flagsRes, 0o666);
|
|
2438
|
+
const r = fs.openSync(resolved_path, _isWin32Flags ? _toWinOpenFlags(flagsRes) : flagsRes, 0o666);
|
|
2260
2439
|
const filetype = wasi.fds.getFileTypeByFd(r);
|
|
2261
2440
|
if ((filetype !== 3 /* WasiFileType.DIRECTORY */) &&
|
|
2262
2441
|
((o_flags & 2 /* WasiFileControlFlag.O_DIRECTORY */) !== 0 ||
|
|
@@ -2292,7 +2471,7 @@ class WASI$1 {
|
|
|
2292
2471
|
const pathString = decoder.decode(unsharedSlice(HEAPU8, path, path + path_len));
|
|
2293
2472
|
const fs = getFs(this);
|
|
2294
2473
|
const resolved_path = await resolvePathAsync(fs, fileDescriptor, pathString, dirflags);
|
|
2295
|
-
const r = await fs.promises.open(resolved_path, flagsRes, 0o666);
|
|
2474
|
+
const r = await fs.promises.open(resolved_path, _isWin32Flags ? _toWinOpenFlags(flagsRes) : flagsRes, 0o666);
|
|
2296
2475
|
const filetype = await wasi.fds.getFileTypeByFd(r);
|
|
2297
2476
|
if ((o_flags & 2 /* WasiFileControlFlag.O_DIRECTORY */) !== 0 && filetype !== 3 /* WasiFileType.DIRECTORY */) {
|
|
2298
2477
|
return 54 /* WasiErrno.ENOTDIR */;
|