Skip to content

Commit 29efaf0

Browse files
committed
Avoid some unneccesary path resolution
There are a bunch of codepaths where we have a node or a stream and we turn it back into a path, then eventually call `lookupPath` on it to turn it back into a node. This removes a few of these instances.
1 parent dfe3356 commit 29efaf0

File tree

2 files changed

+35
-21
lines changed

2 files changed

+35
-21
lines changed

src/library_fs.js

+28-17
Original file line numberDiff line numberDiff line change
@@ -52,7 +52,7 @@ FS.staticInit();
5252
streams: [],
5353
nextInode: 1,
5454
nameTable: null,
55-
currentPath: '/',
55+
currentPath: null,
5656
initialized: false,
5757
// Whether we are currently ignoring permissions. Useful when preparing the
5858
// filesystem and creating files inside read-only folders.
@@ -173,21 +173,22 @@ FS.staticInit();
173173
//
174174
lookupPath(path, opts = {}) {
175175
if (!path) return { path: '', node: null };
176-
opts.follow_mount ??= true
176+
opts.follow_mount ??= true;
177177

178-
if (!PATH.isAbs(path)) {
179-
path = FS.cwd() + '/' + path;
178+
var current;
179+
var current_path;
180+
if (PATH.isAbs(path)) {
181+
current = FS.root;
182+
current_path = "/";
183+
} else {
184+
current = FS.currentNode;
185+
current_path = FS.currentPath;
180186
}
187+
var pathParts = (x) => x.split('/').filter((p) => !!p && (p !== '.'));
188+
var parts = pathParts(path);
181189

182190
// limit max consecutive symlinks to 40 (SYMLOOP_MAX).
183191
linkloop: for (var nlinks = 0; nlinks < 40; nlinks++) {
184-
// split the absolute path
185-
var parts = path.split('/').filter((p) => !!p && (p !== '.'));
186-
187-
// start at the root
188-
var current = FS.root;
189-
var current_path = '/';
190-
191192
for (var i = 0; i < parts.length; i++) {
192193
var islast = (i === parts.length-1);
193194
if (islast && opts.parent) {
@@ -226,10 +227,14 @@ FS.staticInit();
226227
throw new FS.ErrnoError({{{ cDefs.ENOSYS }}});
227228
}
228229
var link = current.node_ops.readlink(current);
229-
if (!PATH.isAbs(link)) {
230-
link = PATH.dirname(current_path) + '/' + link;
230+
if (PATH.isAbs(link)) {
231+
current = FS.root;
232+
current_path = "/";
233+
} else {
234+
current = current.parent;
235+
current_path = PATH.dirname(current_path);
231236
}
232-
path = link + '/' + parts.slice(i + 1).join('/');
237+
parts = [].concat(pathParts(link), parts.slice(i + 1));
233238
continue linkloop;
234239
}
235240
}
@@ -405,7 +410,7 @@ FS.staticInit();
405410
if (!FS.isDir(node.mode)) {
406411
return {{{ cDefs.ENOTDIR }}};
407412
}
408-
if (FS.isRoot(node) || FS.getPath(node) === FS.cwd()) {
413+
if (FS.isRoot(node) || node === FS.currentNode) {
409414
return {{{ cDefs.EBUSY }}};
410415
}
411416
} else {
@@ -886,8 +891,9 @@ FS.staticInit();
886891
#endif
887892
},
888893
readdir(path) {
889-
var lookup = FS.lookupPath(path, { follow: true });
890-
var node = lookup.node;
894+
FS.readdirNode(FS.lookupPath(path, { follow: true }).node);
895+
},
896+
readdirNode(node) {
891897
if (!node.node_ops.readdir) {
892898
throw new FS.ErrnoError({{{ cDefs.ENOTDIR }}});
893899
}
@@ -944,6 +950,9 @@ FS.staticInit();
944950
if (!node) {
945951
throw new FS.ErrnoError({{{ cDefs.ENOENT }}});
946952
}
953+
return FS.statNode(node);
954+
},
955+
statNode(node) {
947956
if (!node.node_ops.getattr) {
948957
throw new FS.ErrnoError({{{ cDefs.EPERM }}});
949958
}
@@ -1366,6 +1375,7 @@ FS.staticInit();
13661375
throw new FS.ErrnoError(errCode);
13671376
}
13681377
FS.currentPath = lookup.path;
1378+
FS.currentNode = lookup.node;
13691379
},
13701380
createDefaultDirectories() {
13711381
FS.mkdir('/tmp');
@@ -1479,6 +1489,7 @@ FS.staticInit();
14791489
FS.nameTable = new Array(4096);
14801490

14811491
FS.mount(MEMFS, {}, '/');
1492+
FS.chdir('/');
14821493

14831494
FS.createDefaultDirectories();
14841495
FS.createDefaultDevices();

src/library_syscall.js

+7-4
Original file line numberDiff line numberDiff line change
@@ -526,7 +526,11 @@ var SyscallsLibrary = {
526526
#endif // ~PROXY_POSIX_SOCKETS==0
527527
__syscall_fchdir: (fd) => {
528528
var stream = SYSCALLS.getStreamFromFD(fd);
529-
FS.chdir(stream.path);
529+
if (!FS.isDir(stream.node.mode)) {
530+
return -{{{ cDefs.ENOTDIR }}};
531+
}
532+
FS.currentPath = stream.path;
533+
FS.currentNode = stream.node;
530534
return 0;
531535
},
532536
__syscall__newselect: (nfds, readfds, writefds, exceptfds, timeout) => {
@@ -689,7 +693,7 @@ var SyscallsLibrary = {
689693
__syscall_getdents64__deps: ['$stringToUTF8'],
690694
__syscall_getdents64: (fd, dirp, count) => {
691695
var stream = SYSCALLS.getStreamFromFD(fd)
692-
stream.getdents ||= FS.readdir(stream.path);
696+
stream.getdents ||= FS.readdirNode(stream.node);
693697
694698
var struct_size = {{{ C_STRUCTS.dirent.__size__ }}};
695699
var pos = 0;
@@ -706,8 +710,7 @@ var SyscallsLibrary = {
706710
type = 4; // DT_DIR
707711
}
708712
else if (name === '..') {
709-
var lookup = FS.lookupPath(stream.path, { parent: true });
710-
id = lookup.node.id;
713+
id = stream.node.parent.id;
711714
type = 4; // DT_DIR
712715
}
713716
else {

0 commit comments

Comments
 (0)