Skip to content

Commit b9a57c3

Browse files
committed
Address review comments
- Add 'use strict' - Make write-symbols main() async
1 parent eb2f628 commit b9a57c3

File tree

2 files changed

+96
-54
lines changed

2 files changed

+96
-54
lines changed

scripts/update-headers.js

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
'use strict';
2+
13
const { createWriteStream } = require('fs');
24
const { Readable } = require('stream');
35
const { finished } = require('stream/promises');

scripts/write-symbols.js

Lines changed: 94 additions & 54 deletions
Original file line numberDiff line numberDiff line change
@@ -1,54 +1,87 @@
1-
const { spawnSync } = require('child_process');
2-
const { resolve } = require('path');
3-
const { writeFileSync } = require('fs');
4-
5-
function getSymbolsForVersion(version) {
6-
const spawned = spawnSync('clang',
7-
['-Xclang', '-ast-dump=json', '-fsyntax-only', '-fno-diagnostics-color', version ? `-DNAPI_VERSION=${version}` : '-DNAPI_EXPERIMENTAL', resolve(__dirname, '..', 'include', 'node_api.h')],
8-
{ maxBuffer: 2_000_000 }
9-
);
10-
11-
if (spawned.error) {
12-
if (spawned.error.code === 'ENOENT') {
13-
throw new Error('This tool requires clang to be installed.');
1+
// @ts-check
2+
'use strict';
3+
4+
const { spawn } = require('child_process');
5+
const { resolve: resolvePath } = require('path');
6+
const { writeFile } = require('fs/promises');
7+
8+
/** @typedef {{ js_native_api_symbols: string[]; node_api_symbols: string[]; }} SymbolInfo */
9+
10+
/**
11+
* @param {number | undefined} [version]
12+
* @returns {Promise<SymbolInfo>}
13+
*/
14+
async function getSymbolsForVersion(version) {
15+
try {
16+
const { exitCode, stdout, stderr } = await new Promise((resolve, reject) => {
17+
const spawned = spawn('clang',
18+
['-Xclang', '-ast-dump=json', '-fsyntax-only', '-fno-diagnostics-color', version ? `-DNAPI_VERSION=${version}` : '-DNAPI_EXPERIMENTAL', resolvePath(__dirname, '..', 'include', 'node_api.h')]
19+
);
20+
21+
let stdout = '';
22+
let stderr = '';
23+
24+
spawned.stdout?.on('data', (data) => {
25+
stdout += data.toString('utf-8');
26+
});
27+
spawned.stderr?.on('data', (data) => {
28+
stderr += data.toString('utf-8');
29+
});
30+
31+
spawned.on('exit', function (exitCode) {
32+
resolve({ exitCode, stdout, stderr });
33+
});
34+
35+
spawned.on('error', function (err) {
36+
reject(err);
37+
});
38+
});
39+
40+
if (exitCode !== 0) {
41+
throw new Error(`clang exited with non-zero exit code ${exitCode}. stderr: ${stderr ? stderr : '<empty>'}`);
1442
}
15-
throw spawned.error;
16-
} else if (spawned.stderr.length > 0) {
17-
throw new Error(spawned.stderr.toString('utf-8'));
18-
}
1943

20-
const ast = JSON.parse(spawned.stdout.toString('utf-8'));
21-
const symbols = { js_native_api_symbols: [], node_api_symbols: [] };
44+
const ast = JSON.parse(stdout);
2245

23-
for (const statement of ast.inner) {
24-
if (statement.kind !== 'FunctionDecl') {
25-
continue;
26-
}
46+
/** @type {{js_native_api_symbols: string[], node_api_symbols: string[]}} */
47+
const symbols = { js_native_api_symbols: [], node_api_symbols: [] };
2748

28-
const name = statement.name;
29-
const file = statement.loc.includedFrom?.file;
49+
for (const statement of ast.inner) {
50+
if (statement.kind !== 'FunctionDecl') {
51+
continue;
52+
}
53+
54+
const name = statement.name;
55+
const file = statement.loc.includedFrom?.file;
3056

31-
if (file) {
32-
symbols.js_native_api_symbols.push(name);
33-
} else {
34-
symbols.node_api_symbols.push(name);
57+
if (file) {
58+
symbols.js_native_api_symbols.push(name);
59+
} else {
60+
symbols.node_api_symbols.push(name);
61+
}
3562
}
36-
}
3763

38-
symbols.js_native_api_symbols.sort();
39-
symbols.node_api_symbols.sort();
64+
symbols.js_native_api_symbols.sort();
65+
symbols.node_api_symbols.sort();
4066

41-
return symbols;
67+
return symbols;
68+
} catch (err) {
69+
if (err.code === 'ENOENT') {
70+
throw new Error('This tool requires clang to be installed.');
71+
}
72+
throw err;
73+
}
4274
}
4375

44-
45-
function getAllSymbols() {
76+
/** @returns {Promise<{maxVersion: number, symbols: {[x: string]: SymbolInfo}}>} */
77+
async function getAllSymbols() {
78+
/** @type {{[x: string]: SymbolInfo}} */
4679
const allSymbols = {};
4780
let version = 1;
4881

4982
console.log('Processing symbols from clang:')
5083
while (true) {
51-
const symbols = getSymbolsForVersion(version);
84+
const symbols = await getSymbolsForVersion(version);
5285

5386
if (version > 1) {
5487
const previousSymbols = allSymbols[`v${version - 1}`];
@@ -62,15 +95,21 @@ function getAllSymbols() {
6295
++version;
6396
}
6497

65-
const symbols = allSymbols[`experimental`] = getSymbolsForVersion();
98+
const symbols = allSymbols[`experimental`] = await getSymbolsForVersion();
6699
console.log(` Experimental: ${symbols.js_native_api_symbols.length} js_native_api_symbols, ${symbols.node_api_symbols.length} node_api_symbols`);
67100
return {
68101
maxVersion: version,
69102
symbols: allSymbols
70103
};
71104
}
72105

106+
/**
107+
* @param {SymbolInfo} previousSymbols
108+
* @param {SymbolInfo} currentSymbols
109+
* @returns {SymbolInfo}
110+
*/
73111
function getUniqueSymbols(previousSymbols, currentSymbols) {
112+
/** @type {SymbolInfo} */
74113
const symbols = { js_native_api_symbols: [], node_api_symbols: [] };
75114
for (const symbol of currentSymbols.js_native_api_symbols) {
76115
if (!previousSymbols.js_native_api_symbols.includes(symbol)) {
@@ -85,22 +124,25 @@ function getUniqueSymbols(previousSymbols, currentSymbols) {
85124
return symbols;
86125
}
87126

88-
function joinSymbols(symbols, prependNewLine) {
89-
if (symbols.length === 0) return '';
90-
return `${prependNewLine ? ',\n ' : ''}'${symbols.join("',\n '")}'`;
127+
/**
128+
* @param {string[]} strings
129+
*/
130+
function joinStrings(strings, prependNewLine = false) {
131+
if (strings.length === 0) return '';
132+
return `${prependNewLine ? ',\n ' : ''}'${strings.join("',\n '")}'`;
91133
}
92134

93-
function getSymbolData() {
94-
const { maxVersion, symbols } = getAllSymbols();
135+
async function getSymbolData() {
136+
const { maxVersion, symbols } = await getAllSymbols();
95137

96138
let data = `'use strict'
97139
98140
const v1 = {
99141
js_native_api_symbols: [
100-
${joinSymbols(symbols.v1.js_native_api_symbols)}
142+
${joinStrings(symbols.v1.js_native_api_symbols)}
101143
],
102144
node_api_symbols: [
103-
${joinSymbols(symbols.v1.node_api_symbols)}
145+
${joinStrings(symbols.v1.node_api_symbols)}
104146
]
105147
}
106148
`;
@@ -111,10 +153,10 @@ const v1 = {
111153
data += `
112154
const ${version === maxVersion + 1 ? 'experimental' : `v${version}`} = {
113155
js_native_api_symbols: [
114-
...v${version - 1}.js_native_api_symbols${joinSymbols(newSymbols.js_native_api_symbols, true)}
156+
...v${version - 1}.js_native_api_symbols${joinStrings(newSymbols.js_native_api_symbols, true)}
115157
],
116158
node_api_symbols: [
117-
...v${version - 1}.node_api_symbols${joinSymbols(newSymbols.node_api_symbols, true)}
159+
...v${version - 1}.node_api_symbols${joinStrings(newSymbols.node_api_symbols, true)}
118160
]
119161
}
120162
`;
@@ -129,16 +171,14 @@ module.exports = {
129171
return data;
130172
}
131173

132-
function main() {
133-
const path = resolve(__dirname, '../symbols.js');
134-
const data = getSymbolData();
174+
async function main() {
175+
const path = resolvePath(__dirname, '../symbols.js');
176+
const data = await getSymbolData();
135177
console.log(`Writing symbols to ${path}`)
136-
writeFileSync(path, data);
178+
return writeFile(path, data);
137179
}
138180

139-
try {
140-
main();
141-
} catch (e) {
181+
main().catch(e => {
142182
console.error(e);
143183
process.exitCode = 1;
144-
}
184+
});

0 commit comments

Comments
 (0)