tools: simplify tools/doc/addon-verify.js

Make the script synchronous and clean it up.  This is preparatory work
for follow-ups commits.

PR-URL: https://github.com/nodejs/node/pull/17407
Reviewed-By: Richard Lau <riclau@uk.ibm.com>
This commit is contained in:
Ben Noordhuis 2018-01-20 01:00:34 +01:00 committed by Ruben Bridgewater
parent 920c13203d
commit c6682636be
No known key found for this signature in database
GPG Key ID: F07496B3EB3C1762

View File

@ -1,5 +1,6 @@
'use strict'; 'use strict';
const { strictEqual } = require('assert');
const fs = require('fs'); const fs = require('fs');
const path = require('path'); const path = require('path');
const marked = require('marked'); const marked = require('marked');
@ -8,52 +9,36 @@ const rootDir = path.resolve(__dirname, '..', '..');
const doc = path.resolve(rootDir, 'doc', 'api', 'addons.md'); const doc = path.resolve(rootDir, 'doc', 'api', 'addons.md');
const verifyDir = path.resolve(rootDir, 'test', 'addons'); const verifyDir = path.resolve(rootDir, 'test', 'addons');
const contents = fs.readFileSync(doc).toString();
const tokens = marked.lexer(contents);
let id = 0; let id = 0;
let currentHeader; let currentHeader;
const addons = {}; const addons = {};
tokens.forEach((token) => { const content = fs.readFileSync(doc, 'utf8');
if (token.type === 'heading' && token.text) { for (const { text, type } of marked.lexer(content)) {
currentHeader = token.text; if (type === 'heading' && text) {
currentHeader = text;
addons[currentHeader] = { addons[currentHeader] = {
files: {} files: {}
}; };
} }
if (token.type === 'code') { if (type === 'code') {
var match = token.text.match(/^\/\/\s+(.*\.(?:cc|h|js))[\r\n]/); const match = text.match(/^\/\/\s+(.*\.(?:cc|h|js))[\r\n]/);
if (match !== null) { if (match !== null) {
addons[currentHeader].files[match[1]] = token.text; addons[currentHeader].files[match[1]] = text;
} }
} }
});
for (var header in addons) {
verifyFiles(addons[header].files,
header,
console.log.bind(null, 'wrote'),
function(err) { if (err) throw err; });
} }
function once(fn) { for (const header in addons) {
var once = false; let { files } = addons[header];
return function() {
if (once)
return;
once = true;
fn.apply(this, arguments);
};
}
function verifyFiles(files, blockName, onprogress, ondone) {
// must have a .cc and a .js to be a valid test // must have a .cc and a .js to be a valid test
if (!Object.keys(files).some((name) => /\.cc$/.test(name)) || if (!Object.keys(files).some((name) => /\.cc$/.test(name)) ||
!Object.keys(files).some((name) => /\.js$/.test(name))) { !Object.keys(files).some((name) => /\.js$/.test(name))) {
return; continue;
} }
blockName = blockName const blockName = header
.toLowerCase() .toLowerCase()
.replace(/\s/g, '_') .replace(/\s/g, '_')
.replace(/[^a-z\d_]/g, ''); .replace(/[^a-z\d_]/g, '');
@ -62,21 +47,9 @@ function verifyFiles(files, blockName, onprogress, ondone) {
`${(++id < 10 ? '0' : '') + id}_${blockName}` `${(++id < 10 ? '0' : '') + id}_${blockName}`
); );
files = Object.keys(files).map(function(name) { files = Object.entries(files).map(([name, content]) => {
if (name === 'test.js') { if (name === 'test.js') content = boilerplate(name, content);
files[name] = `'use strict'; return { name, content, path: path.resolve(dir, name) };
const common = require('../../common');
${files[name].replace(
"'./build/Release/addon'",
// eslint-disable-next-line no-template-curly-in-string
'`./build/${common.buildType}/addon`')}
`;
}
return {
path: path.resolve(dir, name),
name: name,
content: files[name]
};
}); });
files.push({ files.push({
@ -84,7 +57,7 @@ ${files[name].replace(
content: JSON.stringify({ content: JSON.stringify({
targets: [ targets: [
{ {
target_name: 'addon', target_name: 'binding',
defines: [ 'V8_DEPRECATION_WARNINGS=1' ], defines: [ 'V8_DEPRECATION_WARNINGS=1' ],
sources: files.map(function(file) { sources: files.map(function(file) {
return file.name; return file.name;
@ -94,22 +67,34 @@ ${files[name].replace(
}) })
}); });
fs.mkdir(dir, function() { try {
// Ignore errors fs.mkdirSync(dir);
} catch (e) {
strictEqual(e.code, 'EEXIST');
}
const done = once(ondone); for (const file of files) {
var waiting = files.length; let content;
files.forEach(function(file) { try {
fs.writeFile(file.path, file.content, function(err) { content = fs.readFileSync(file.path, 'utf8');
if (err) } catch (e) {
return done(err); strictEqual(e.code, 'ENOENT');
}
if (onprogress) // Only update when file content has changed to prevent unneeded rebuilds.
onprogress(file.path); if (content !== file.content) {
fs.writeFileSync(file.path, file.content);
if (--waiting === 0) console.log('wrote', file.path);
done(); }
}); }
}); }
});
function boilerplate(name, content) {
return `'use strict';
const common = require('../../common');
${content.replace(
"'./build/Release/binding'",
// eslint-disable-next-line no-template-curly-in-string
'`./build/${common.buildType}/binding`')}
`;
} }