Skip to content

Commit 36ec459

Browse files
committed
vfs: use path.posix methods instead of custom implementations
1 parent 1300143 commit 36ec459

File tree

3 files changed

+31
-56
lines changed

3 files changed

+31
-56
lines changed

lib/internal/vfs/providers/memory.js

Lines changed: 18 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ const {
88
} = primordials;
99

1010
const { Buffer } = require('buffer');
11+
const { posix: pathPosix } = require('path');
1112
const { VirtualProvider } = require('internal/vfs/provider');
1213
const { MemoryFileHandle } = require('internal/vfs/file_handle');
1314
const {
@@ -169,27 +170,14 @@ class MemoryProvider extends VirtualProvider {
169170
* @returns {string} Normalized path
170171
*/
171172
_normalizePath(path) {
172-
// Normalize slashes
173+
// Convert backslashes to forward slashes
173174
let normalized = path.replace(/\\/g, '/');
175+
// Ensure absolute path
174176
if (!normalized.startsWith('/')) {
175177
normalized = '/' + normalized;
176178
}
177-
178-
// Split into segments and resolve . and ..
179-
const segments = normalized.split('/').filter((s) => s !== '' && s !== '.');
180-
const resolved = [];
181-
for (const segment of segments) {
182-
if (segment === '..') {
183-
// Go up one level (but don't go above root)
184-
if (resolved.length > 0) {
185-
resolved.pop();
186-
}
187-
} else {
188-
resolved.push(segment);
189-
}
190-
}
191-
192-
return '/' + resolved.join('/');
179+
// Use path.posix.normalize to resolve . and ..
180+
return pathPosix.normalize(normalized);
193181
}
194182

195183
/**
@@ -213,11 +201,7 @@ class MemoryProvider extends VirtualProvider {
213201
if (path === '/') {
214202
return null;
215203
}
216-
const lastSlash = path.lastIndexOf('/');
217-
if (lastSlash === 0) {
218-
return '/';
219-
}
220-
return path.slice(0, lastSlash);
204+
return pathPosix.dirname(path);
221205
}
222206

223207
/**
@@ -226,8 +210,7 @@ class MemoryProvider extends VirtualProvider {
226210
* @returns {string} Base name
227211
*/
228212
_getBaseName(path) {
229-
const lastSlash = path.lastIndexOf('/');
230-
return path.slice(lastSlash + 1);
213+
return pathPosix.basename(path);
231214
}
232215

233216
/**
@@ -241,11 +224,8 @@ class MemoryProvider extends VirtualProvider {
241224
return this._normalizePath(target);
242225
}
243226
// Relative target: resolve against symlink's parent directory
244-
const parentPath = this._getParentPath(symlinkPath);
245-
if (parentPath === null) {
246-
return this._normalizePath('/' + target);
247-
}
248-
return this._normalizePath(parentPath + '/' + target);
227+
const parentPath = this._getParentPath(symlinkPath) || '/';
228+
return this._normalizePath(pathPosix.join(parentPath, target));
249229
}
250230

251231
/**
@@ -264,7 +244,7 @@ class MemoryProvider extends VirtualProvider {
264244

265245
const segments = this._splitPath(normalized);
266246
let current = this[kRoot];
267-
let currentPath = '';
247+
let currentPath = '/';
268248

269249
for (let i = 0; i < segments.length; i++) {
270250
const segment = segments[i];
@@ -291,14 +271,14 @@ class MemoryProvider extends VirtualProvider {
291271
}
292272

293273
// Ensure directory is populated before accessing children
294-
this._ensurePopulated(current, currentPath || '/');
274+
this._ensurePopulated(current, currentPath);
295275

296276
const entry = current.children.get(segment);
297277
if (!entry) {
298278
return { entry: null, resolvedPath: null };
299279
}
300280

301-
currentPath = currentPath + '/' + segment;
281+
currentPath = pathPosix.join(currentPath, segment);
302282
current = entry;
303283
}
304284

@@ -353,7 +333,7 @@ class MemoryProvider extends VirtualProvider {
353333

354334
// Follow symlinks in parent path
355335
if (current.isSymbolicLink()) {
356-
const currentPath = '/' + segments.slice(0, i).join('/');
336+
const currentPath = pathPosix.join('/', ...segments.slice(0, i));
357337
const targetPath = this._resolveSymlinkTarget(currentPath, current.target);
358338
const result = this._lookupEntry(targetPath, true, 0);
359339
if (!result.entry) {
@@ -367,8 +347,8 @@ class MemoryProvider extends VirtualProvider {
367347
}
368348

369349
// Ensure directory is populated before accessing children
370-
const currentPath = '/' + segments.slice(0, i).join('/');
371-
this._ensurePopulated(current, currentPath || '/');
350+
const currentPath = pathPosix.join('/', ...segments.slice(0, i));
351+
this._ensurePopulated(current, currentPath);
372352

373353
let entry = current.children.get(segment);
374354
if (!entry) {
@@ -388,7 +368,7 @@ class MemoryProvider extends VirtualProvider {
388368
}
389369

390370
// Ensure final directory is populated
391-
const finalPath = '/' + segments.join('/');
371+
const finalPath = pathPosix.join('/', ...segments);
392372
this._ensurePopulated(current, finalPath);
393373

394374
return current;
@@ -578,10 +558,10 @@ class MemoryProvider extends VirtualProvider {
578558
// Create all parent directories
579559
const segments = this._splitPath(normalized);
580560
let current = this[kRoot];
581-
let currentPath = '';
561+
let currentPath = '/';
582562

583563
for (const segment of segments) {
584-
currentPath = currentPath + '/' + segment;
564+
currentPath = pathPosix.join(currentPath, segment);
585565
let entry = current.children.get(segment);
586566
if (!entry) {
587567
entry = new MemoryEntry(TYPE_DIR, { mode: options?.mode });

lib/internal/vfs/providers/sea.js

Lines changed: 10 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ const {
1111
} = primordials;
1212

1313
const { Buffer } = require('buffer');
14+
const { posix: pathPosix } = require('path');
1415
const { VirtualProvider } = require('internal/vfs/provider');
1516
const { VirtualFileHandle } = require('internal/vfs/file_handle');
1617
const {
@@ -168,10 +169,10 @@ class SEAProvider extends VirtualProvider {
168169

169170
// Derive parent directories
170171
const parts = path.split('/').filter(Boolean);
171-
let currentPath = '';
172+
let currentPath = '/';
172173
for (let j = 0; j < parts.length - 1; j++) {
173-
const parentPath = currentPath || '/';
174-
currentPath = currentPath + '/' + parts[j];
174+
const parentPath = currentPath;
175+
currentPath = pathPosix.join(currentPath, parts[j]);
175176

176177
if (!this[kDirectories].has(currentPath)) {
177178
this[kDirectories].set(currentPath, new SafeSet());
@@ -186,8 +187,8 @@ class SEAProvider extends VirtualProvider {
186187

187188
// Add file to parent directory's children
188189
if (parts.length > 0) {
189-
const fileName = parts[parts.length - 1];
190-
const parentPath = parts.length === 1 ? '/' : '/' + parts.slice(0, -1).join('/');
190+
const fileName = pathPosix.basename(path);
191+
const parentPath = pathPosix.dirname(path);
191192

192193
if (!this[kDirectories].has(parentPath)) {
193194
this[kDirectories].set(parentPath, new SafeSet());
@@ -212,14 +213,14 @@ class SEAProvider extends VirtualProvider {
212213
* @returns {string} Normalized path
213214
*/
214215
_normalizePath(path) {
216+
// Convert backslashes to forward slashes
215217
let normalized = path.replace(/\\/g, '/');
216-
if (normalized !== '/' && normalized.endsWith('/')) {
217-
normalized = normalized.slice(0, -1);
218-
}
218+
// Ensure absolute path
219219
if (!normalized.startsWith('/')) {
220220
normalized = '/' + normalized;
221221
}
222-
return normalized;
222+
// Use path.posix.normalize to resolve . and .. and remove trailing slashes
223+
return pathPosix.normalize(normalized);
223224
}
224225

225226
/**

lib/internal/vfs/router.js

Lines changed: 3 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -2,14 +2,13 @@
22

33
const {
44
StringPrototypeEndsWith,
5-
StringPrototypeLastIndexOf,
65
StringPrototypeReplaceAll,
76
StringPrototypeSlice,
87
StringPrototypeSplit,
98
StringPrototypeStartsWith,
109
} = primordials;
1110

12-
const { basename, isAbsolute, resolve, sep } = require('path');
11+
const { isAbsolute, posix: pathPosix, resolve, sep } = require('path');
1312

1413
/**
1514
* Normalizes a path for VFS lookup.
@@ -60,11 +59,7 @@ function getParentPath(normalizedPath) {
6059
if (normalizedPath === '/') {
6160
return null;
6261
}
63-
const lastSlash = StringPrototypeLastIndexOf(normalizedPath, '/');
64-
if (lastSlash === 0) {
65-
return '/';
66-
}
67-
return StringPrototypeSlice(normalizedPath, 0, lastSlash);
62+
return pathPosix.dirname(normalizedPath);
6863
}
6964

7065
/**
@@ -73,8 +68,7 @@ function getParentPath(normalizedPath) {
7368
* @returns {string} The base name
7469
*/
7570
function getBaseName(normalizedPath) {
76-
// Basename works correctly for VFS paths since they use forward slashes
77-
return basename(normalizedPath);
71+
return pathPosix.basename(normalizedPath);
7872
}
7973

8074
/**

0 commit comments

Comments
 (0)