Skip to content

Commit bdfbe0f

Browse files
committed
Tread a failing opendir as an empty dir
1 parent d367b6e commit bdfbe0f

File tree

2 files changed

+46
-12
lines changed

2 files changed

+46
-12
lines changed

packages/host/src/node/path-utils.test.ts

Lines changed: 23 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -62,9 +62,9 @@ describe("isNodeApiModule", () => {
6262
assert(isNodeApiModule(path.join(tempDirectoryPath, "addon.node")));
6363
});
6464

65-
// there is no way to set ACLs on directories in Node.js on Windows with brittle powershell commands
6665
it(
6766
"returns false when directory cannot be read due to permissions",
67+
// Skipping on Windows because there is no way to set ACLs on directories in Node.js on Windows without brittle powershell commands
6868
{ skip: process.platform === "win32" },
6969
(context) => {
7070
const tempDirectoryPath = setupTempDirectory(context, {
@@ -367,6 +367,28 @@ describe("findNodeApiModulePaths", () => {
367367
path.join(tempDir, "node_modules/root.apple.node"),
368368
]);
369369
});
370+
371+
it(
372+
"returns empty when directory cannot be read due to permissions",
373+
// Skipping on Windows because there is no way to set ACLs on directories in Node.js on Windows without brittle powershell commands
374+
{ skip: process.platform === "win32" },
375+
async (context) => {
376+
const tempDir = setupTempDirectory(context, {
377+
"addon.apple.node/react-native-node-api-module": "",
378+
});
379+
380+
removeReadPermissions(tempDir);
381+
try {
382+
const result = findNodeApiModulePaths({
383+
fromPath: tempDir,
384+
platform: "apple",
385+
});
386+
assert.deepEqual(await result, []);
387+
} finally {
388+
restoreReadPermissions(tempDir);
389+
}
390+
}
391+
);
370392
});
371393

372394
describe("determineModuleContext", () => {

packages/host/src/node/path-utils.ts

Lines changed: 23 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -327,20 +327,32 @@ export async function findNodeApiModulePaths(
327327
const result: string[] = [];
328328
const pendingResults: Promise<string[]>[] = [];
329329

330-
for await (const dirent of await fs.promises.opendir(candidatePath)) {
330+
try {
331+
for await (const dirent of await fs.promises.opendir(candidatePath)) {
332+
if (
333+
dirent.isFile() &&
334+
dirent.name === MAGIC_FILENAME &&
335+
hasPlatformExtension(platform, candidatePath)
336+
) {
337+
result.push(candidatePath);
338+
} else if (dirent.isDirectory()) {
339+
// Traverse into the child directory
340+
// Pushing result into a list instead of awaiting immediately to parallelize the search
341+
pendingResults.push(
342+
findNodeApiModulePaths(options, path.join(suffix, dirent.name))
343+
);
344+
}
345+
}
346+
} catch (error) {
331347
if (
332-
dirent.isFile() &&
333-
dirent.name === MAGIC_FILENAME &&
334-
hasPlatformExtension(platform, candidatePath)
348+
error instanceof Error &&
349+
"code" in error &&
350+
(error.code === "ENOENT" || error.code === "EACCES")
335351
) {
336-
result.push(candidatePath);
337-
} else if (dirent.isDirectory()) {
338-
// Traverse into the child directory
339-
// Pushing result into a list instead of awaiting immediately to parallelize the search
340-
pendingResults.push(
341-
findNodeApiModulePaths(options, path.join(suffix, dirent.name))
342-
);
352+
// Gracefully handling issues with reading directories
353+
return [];
343354
}
355+
throw error;
344356
}
345357
const childResults = await Promise.all(pendingResults);
346358
result.push(...childResults.flatMap((filePath) => filePath));

0 commit comments

Comments
 (0)