Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
28 changes: 28 additions & 0 deletions packages/host/src/node/path-utils.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import fswin from "fswin";
import {
determineModuleContext,
findNodeApiModulePaths,
findNodeAddonForBindings,
findPackageDependencyPaths,
getLibraryName,
isNodeApiModule,
Expand Down Expand Up @@ -372,3 +373,30 @@ describe("determineModuleContext", () => {
assert.equal(readCount, 1);
});
});

describe("findNodeAddonForBindings()", () => {
const expectedPaths = {
"addon_1": "addon_1.node",
"addon_2": "build/Release/addon_2.node",
"addon_3": "build/Debug/addon_3.node",
"addon_4": "build/addon_4.node",
"addon_5": "out/Release/addon_5.node",
"addon_6": "out/Debug/addon_6.node",
"addon_7": "Release/addon_7.node",
"addon_8": "Debug/addon_8.node",
};

for (const [name, relPath] of Object.entries(expectedPaths)) {
it(`should look for addons in common paths (${name} in "${relPath}")`, (context) => {
// Arrange
const tempDirectoryPath = setupTempDirectory(context, {
[relPath]: "// This is supposed to be a binary file",
});
// Act
const actualPath = findNodeAddonForBindings(name, tempDirectoryPath);
// Assert
const expectedAbsPath = path.join(tempDirectoryPath, relPath);
assert.equal(actualPath, expectedAbsPath);
});
}
});
35 changes: 35 additions & 0 deletions packages/host/src/node/path-utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,15 @@ const packageNameCache = new Map<string, string>();
* TODO: Consider checking for a specific platform extension.
*/
export function isNodeApiModule(modulePath: string): boolean {
{
// HACK: Take a shortcut (if applicable): existing `.node` files are addons
try {
fs.accessSync(modulePath.endsWith(".node") ? modulePath : `${modulePath}.node`);
return true;
} catch {
// intentionally left empty
}
}
const dir = path.dirname(modulePath);
const baseName = path.basename(modulePath, ".node");
let entries: string[];
Expand Down Expand Up @@ -385,3 +394,29 @@ export function getLatestMtime(fromPath: string): number {

return latest;
}

// NOTE: List of paths influenced by `node-bindings` itself
// https://github.com/TooTallNate/node-bindings/blob/v1.3.0/bindings.js#L21
const nodeBindingsSubdirs = [
"./",
"./build/Release",
"./build/Debug",
"./build",
"./out/Release",
"./out/Debug",
"./Release",
"./Debug",
];

export function findNodeAddonForBindings(id: string, fromDir: string) {
const idWithExt = id.endsWith(".node") ? id : `${id}.node`;
// Support traversing the filesystem to find the Node-API module.
// Currently, we check the most common directories like `bindings` does.
for (const subdir of nodeBindingsSubdirs) {
const resolvedPath = path.join(fromDir, subdir, idWithExt);
if (isNodeApiModule(resolvedPath)) {
return resolvedPath;
}
}
return undefined;
}
Loading