UNPKG

3.21 kBJavaScriptView Raw
1'use strict';
2// Descend into a directory structure and, for each file matching *.node, output
3// based on the imports found in the file whether it's an N-API module or not.
4
5const fs = require('fs');
6const path = require('path');
7const child_process = require('child_process');
8
9// Read the output of the command, break it into lines, and use the reducer to
10// decide whether the file is an N-API module or not.
11function checkFile(file, command, argv, reducer) {
12 const child = child_process.spawn(command, argv, {
13 stdio: ['inherit', 'pipe', 'inherit']
14 });
15 let leftover = '';
16 let isNapi = undefined;
17 child.stdout.on('data', (chunk) => {
18 if (isNapi === undefined) {
19 chunk = (leftover + chunk.toString()).split(/[\r\n]+/);
20 leftover = chunk.pop();
21 isNapi = chunk.reduce(reducer, isNapi);
22 if (isNapi !== undefined) {
23 child.kill();
24 }
25 }
26 });
27 child.on('close', (code, signal) => {
28 if ((code === null && signal !== null) || (code !== 0)) {
29 console.log(
30 command + ' exited with code: ' + code + ' and signal: ' + signal);
31 } else {
32 // Green if it's a N-API module, red otherwise.
33 console.log(
34 '\x1b[' + (isNapi ? '42' : '41') + 'm' +
35 (isNapi ? ' N-API' : 'Not N-API') +
36 '\x1b[0m: ' + file);
37 }
38 });
39}
40
41// Use nm -a to list symbols.
42function checkFileUNIX(file) {
43 checkFile(file, 'nm', ['-a', file], (soFar, line) => {
44 if (soFar === undefined) {
45 line = line.match(/([0-9a-f]*)? ([a-zA-Z]) (.*$)/);
46 if (line[2] === 'U') {
47 if (/^napi/.test(line[3])) {
48 soFar = true;
49 }
50 }
51 }
52 return soFar;
53 });
54}
55
56// Use dumpbin /imports to list symbols.
57function checkFileWin32(file) {
58 checkFile(file, 'dumpbin', ['/imports', file], (soFar, line) => {
59 if (soFar === undefined) {
60 line = line.match(/([0-9a-f]*)? +([a-zA-Z0-9]) (.*$)/);
61 if (line && /^napi/.test(line[line.length - 1])) {
62 soFar = true;
63 }
64 }
65 return soFar;
66 });
67}
68
69// Descend into a directory structure and pass each file ending in '.node' to
70// one of the above checks, depending on the OS.
71function recurse(top) {
72 fs.readdir(top, (error, items) => {
73 if (error) {
74 throw ("error reading directory " + top + ": " + error);
75 }
76 items.forEach((item) => {
77 item = path.join(top, item);
78 fs.stat(item, ((item) => (error, stats) => {
79 if (error) {
80 throw ("error about " + item + ": " + error);
81 }
82 if (stats.isDirectory()) {
83 recurse(item);
84 } else if (/[.]node$/.test(item) &&
85 // Explicitly ignore files called 'nothing.node' because they are
86 // artefacts of node-addon-api having identified a version of
87 // Node.js that ships with a correct implementation of N-API.
88 path.basename(item) !== 'nothing.node') {
89 process.platform === 'win32' ?
90 checkFileWin32(item) :
91 checkFileUNIX(item);
92 }
93 })(item));
94 });
95 });
96}
97
98// Start with the directory given on the command line or the current directory
99// if nothing was given.
100recurse(process.argv.length > 3 ? process.argv[2] : '.');