test/style: refactor parser task
This commit is contained in:
committed by
Nils Knappmeier
parent
dde108e283
commit
3a5b65e02b
+28
-34
@@ -1,39 +1,33 @@
|
|||||||
const childProcess = require('child_process');
|
const { execFileWithInheritedOutput } = require('./util/exec-file');
|
||||||
|
const { createRegisterAsyncTaskFn } = require('./util/async-grunt-task');
|
||||||
|
|
||||||
|
const OUTPUT_FILE = 'lib/handlebars/compiler/parser.js';
|
||||||
|
|
||||||
module.exports = function(grunt) {
|
module.exports = function(grunt) {
|
||||||
grunt.registerTask('parser', 'Generate jison parser.', function() {
|
const registerAsyncTask = createRegisterAsyncTaskFn(grunt);
|
||||||
const done = this.async();
|
|
||||||
|
|
||||||
let cmd = './node_modules/.bin/jison';
|
registerAsyncTask('parser', async () => {
|
||||||
|
await runJison();
|
||||||
if (process.platform === 'win32') {
|
combineWithPrefixAndSuffix();
|
||||||
cmd = 'node_modules\\.bin\\jison.cmd';
|
grunt.log.writeln(`Parser "${OUTPUT_FILE}" created.`);
|
||||||
}
|
|
||||||
|
|
||||||
const child = childProcess.spawn(
|
|
||||||
cmd,
|
|
||||||
['-m', 'js', 'src/handlebars.yy', 'src/handlebars.l'],
|
|
||||||
{ stdio: 'inherit' }
|
|
||||||
);
|
|
||||||
child.on('exit', function(code) {
|
|
||||||
if (code != 0) {
|
|
||||||
grunt.fatal('Jison failure: ' + code);
|
|
||||||
done();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
const src = [
|
|
||||||
'src/parser-prefix.js',
|
|
||||||
'handlebars.js',
|
|
||||||
'src/parser-suffix.js'
|
|
||||||
]
|
|
||||||
.map(grunt.file.read)
|
|
||||||
.join('');
|
|
||||||
grunt.file.delete('handlebars.js');
|
|
||||||
|
|
||||||
grunt.file.write('lib/handlebars/compiler/parser.js', src);
|
|
||||||
grunt.log.writeln('Parser "lib/handlebars/compiler/parser.js" created.');
|
|
||||||
done();
|
|
||||||
});
|
|
||||||
});
|
});
|
||||||
|
|
||||||
|
async function runJison() {
|
||||||
|
await execFileWithInheritedOutput('jison', [
|
||||||
|
'-m',
|
||||||
|
'js',
|
||||||
|
'src/handlebars.yy',
|
||||||
|
'src/handlebars.l'
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
|
||||||
|
function combineWithPrefixAndSuffix() {
|
||||||
|
const combinedParserSourceCode =
|
||||||
|
grunt.file.read('src/parser-prefix.js') +
|
||||||
|
grunt.file.read('handlebars.js') +
|
||||||
|
grunt.file.read('src/parser-suffix.js');
|
||||||
|
|
||||||
|
grunt.file.write(OUTPUT_FILE, combinedParserSourceCode);
|
||||||
|
grunt.file.delete('handlebars.js');
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|||||||
+36
-46
@@ -1,55 +1,45 @@
|
|||||||
const childProcess = require('child_process'),
|
const childProcess = require('child_process'),
|
||||||
fs = require('fs'),
|
fs = require('fs'),
|
||||||
os = require('os'),
|
os = require('os'),
|
||||||
expect = require('chai').expect,
|
expect = require('chai').expect;
|
||||||
util = require('util');
|
|
||||||
|
|
||||||
const readFile = util.promisify(fs.readFile);
|
|
||||||
const execFile = util.promisify(childProcess.execFile);
|
|
||||||
|
|
||||||
module.exports = function(grunt) {
|
module.exports = function(grunt) {
|
||||||
grunt.registerTask(
|
grunt.registerTask('test:bin', function() {
|
||||||
'test:bin',
|
const stdout = executeBinHandlebars(
|
||||||
wrapAsync(async function() {
|
'-a',
|
||||||
const { stdout } = await execFileWithWin32Fallback('./bin/handlebars', [
|
'spec/artifacts/empty.handlebars'
|
||||||
'-a',
|
);
|
||||||
'spec/artifacts/empty.handlebars'
|
|
||||||
]);
|
|
||||||
|
|
||||||
const expectedOutput = await readFile(
|
const expectedOutput = fs.readFileSync(
|
||||||
'./spec/expected/empty.amd.js',
|
'./spec/expected/empty.amd.js',
|
||||||
'utf-8'
|
'utf-8'
|
||||||
);
|
);
|
||||||
|
|
||||||
const normalizedOutput = normalizeCrlf(stdout);
|
const normalizedOutput = normalizeCrlf(stdout);
|
||||||
const normalizedExpectedOutput = normalizeCrlf(expectedOutput);
|
const normalizedExpectedOutput = normalizeCrlf(expectedOutput);
|
||||||
expect(normalizedOutput).to.equal(normalizedExpectedOutput);
|
|
||||||
})
|
|
||||||
);
|
|
||||||
|
|
||||||
async function execFileWithWin32Fallback(command, args) {
|
expect(normalizedOutput).to.equal(normalizedExpectedOutput);
|
||||||
// On Windows, the executable handlebars.js file cannot be run directly
|
});
|
||||||
if (os.platform() === 'win32') {
|
|
||||||
args.unshift(command);
|
|
||||||
command = process.argv[0];
|
|
||||||
}
|
|
||||||
return execFile(command, args, { encoding: 'utf-8' });
|
|
||||||
}
|
|
||||||
|
|
||||||
function normalizeCrlf(string) {
|
|
||||||
if (string != null) {
|
|
||||||
return string.replace(/\r\n/g, '\n');
|
|
||||||
}
|
|
||||||
return string;
|
|
||||||
}
|
|
||||||
|
|
||||||
function wrapAsync(asyncFunction) {
|
|
||||||
return function() {
|
|
||||||
asyncFunction()
|
|
||||||
.catch(error => {
|
|
||||||
grunt.fatal(error);
|
|
||||||
})
|
|
||||||
.finally(this.async());
|
|
||||||
};
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// helper functions
|
||||||
|
|
||||||
|
function executeBinHandlebars(...args) {
|
||||||
|
if (os.platform() === 'win32') {
|
||||||
|
// On Windows, the executable handlebars.js file cannot be run directly
|
||||||
|
const nodeJs = process.argv[0];
|
||||||
|
return execFilesSyncUtf8(nodeJs, ['./bin/handlebars'].concat(args));
|
||||||
|
}
|
||||||
|
return execFilesSyncUtf8('./bin/handlebars', args);
|
||||||
|
}
|
||||||
|
|
||||||
|
function execFilesSyncUtf8(command, args) {
|
||||||
|
return childProcess.execFileSync(command, args, { encoding: 'utf-8' });
|
||||||
|
}
|
||||||
|
|
||||||
|
function normalizeCrlf(string) {
|
||||||
|
if (typeof string === 'string') {
|
||||||
|
return string.replace(/\r\n/g, '\n');
|
||||||
|
}
|
||||||
|
return string;
|
||||||
|
}
|
||||||
|
|||||||
+26
-56
@@ -1,66 +1,36 @@
|
|||||||
const childProcess = require('child_process');
|
const { execNodeJsScriptWithInheritedOutput } = require('./util/exec-file');
|
||||||
|
const { createRegisterAsyncTaskFn } = require('./util/async-grunt-task');
|
||||||
|
|
||||||
module.exports = function(grunt) {
|
module.exports = function(grunt) {
|
||||||
grunt.registerTask(
|
const registerAsyncTask = createRegisterAsyncTaskFn(grunt);
|
||||||
'test:mocha',
|
|
||||||
promiseBasedTask(async () => forkAndWait('./spec/env/runner'))
|
registerAsyncTask('test:mocha', async () =>
|
||||||
|
execNodeJsScriptWithInheritedOutput('./spec/env/runner')
|
||||||
);
|
);
|
||||||
|
|
||||||
grunt.registerTask(
|
registerAsyncTask('test:cov', async () =>
|
||||||
'test:cov',
|
execNodeJsScriptWithInheritedOutput('node_modules/istanbul/lib/cli.js', [
|
||||||
promiseBasedTask(async () =>
|
'cover',
|
||||||
forkAndWait(
|
'--source-map',
|
||||||
'node_modules/istanbul/lib/cli.js',
|
'--',
|
||||||
'cover',
|
'./spec/env/runner.js'
|
||||||
'--source-map',
|
])
|
||||||
'--',
|
|
||||||
'./spec/env/runner.js'
|
|
||||||
)
|
|
||||||
)
|
|
||||||
);
|
);
|
||||||
|
|
||||||
grunt.registerTask(
|
registerAsyncTask('test:min', async () =>
|
||||||
'test:min',
|
execNodeJsScriptWithInheritedOutput('./spec/env/runner', ['--min'])
|
||||||
promiseBasedTask(async () => forkAndWait('./spec/env/runner', '--min'))
|
|
||||||
);
|
);
|
||||||
|
|
||||||
grunt.registerTask(
|
registerAsyncTask('test:check-cov', async () =>
|
||||||
'test:check-cov',
|
execNodeJsScriptWithInheritedOutput('node_modules/istanbul/lib/cli.js', [
|
||||||
promiseBasedTask(() =>
|
'check-coverage',
|
||||||
forkAndWait(
|
'--statements',
|
||||||
'node_modules/istanbul/lib/cli.js',
|
'100',
|
||||||
'check-coverage',
|
'--functions',
|
||||||
'--statements',
|
'100',
|
||||||
'100',
|
'--branches',
|
||||||
'--functions',
|
'100',
|
||||||
'100',
|
'--lines 100'
|
||||||
'--branches',
|
])
|
||||||
'100',
|
|
||||||
'--lines 100'
|
|
||||||
)
|
|
||||||
)
|
|
||||||
);
|
);
|
||||||
|
|
||||||
function promiseBasedTask(asyncFunction) {
|
|
||||||
return function() {
|
|
||||||
asyncFunction()
|
|
||||||
.catch(error => {
|
|
||||||
grunt.fatal(error);
|
|
||||||
})
|
|
||||||
.finally(this.async());
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
async function forkAndWait(command, ...args) {
|
|
||||||
return new Promise((resolve, reject) => {
|
|
||||||
const child = childProcess.fork(command, args, { stdio: 'inherit' });
|
|
||||||
child.on('close', code => {
|
|
||||||
if (code !== 0) {
|
|
||||||
reject(new Error(`Child process failed with exit-code ${code}`));
|
|
||||||
}
|
|
||||||
});
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
grunt.registerTask('test', ['test:bin', 'test:cov', 'test:check-cov']);
|
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -0,0 +1,13 @@
|
|||||||
|
module.exports = { createRegisterAsyncTaskFn };
|
||||||
|
|
||||||
|
function createRegisterAsyncTaskFn(grunt) {
|
||||||
|
return function registerAsyncTask(name, asyncFunction) {
|
||||||
|
grunt.registerTask(name, function() {
|
||||||
|
asyncFunction()
|
||||||
|
.catch(error => {
|
||||||
|
grunt.fatal(error);
|
||||||
|
})
|
||||||
|
.finally(this.async());
|
||||||
|
});
|
||||||
|
};
|
||||||
|
}
|
||||||
@@ -0,0 +1,51 @@
|
|||||||
|
const childProcess = require('child_process');
|
||||||
|
const fs = require('fs');
|
||||||
|
const path = require('path');
|
||||||
|
|
||||||
|
module.exports = {
|
||||||
|
execNodeJsScriptWithInheritedOutput,
|
||||||
|
execFileWithInheritedOutput
|
||||||
|
};
|
||||||
|
|
||||||
|
async function execNodeJsScriptWithInheritedOutput(command, args) {
|
||||||
|
return new Promise((resolve, reject) => {
|
||||||
|
const child = childProcess.fork(command, args, { stdio: 'inherit' });
|
||||||
|
child.on('close', code => {
|
||||||
|
if (code !== 0) {
|
||||||
|
reject(new Error(`Child process failed with exit-code ${code}`));
|
||||||
|
}
|
||||||
|
resolve();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
async function execFileWithInheritedOutput(command, args) {
|
||||||
|
return new Promise((resolve, reject) => {
|
||||||
|
const resolvedCommand = preferLocalDependencies(command);
|
||||||
|
const child = childProcess.spawn(resolvedCommand, args, {
|
||||||
|
stdio: 'inherit'
|
||||||
|
});
|
||||||
|
child.on('exit', code => {
|
||||||
|
if (code !== 0) {
|
||||||
|
reject(new Error(`Child process failed with exit-code ${code}`));
|
||||||
|
}
|
||||||
|
resolve();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
function preferLocalDependencies(command) {
|
||||||
|
const localCandidate = resolveLocalCandidate(command);
|
||||||
|
|
||||||
|
if (fs.existsSync(localCandidate)) {
|
||||||
|
return localCandidate;
|
||||||
|
}
|
||||||
|
return command;
|
||||||
|
}
|
||||||
|
|
||||||
|
function resolveLocalCandidate(command) {
|
||||||
|
if (process.platform === 'win32') {
|
||||||
|
return path.join('node_modules', '.bin', command + '.cmd');
|
||||||
|
}
|
||||||
|
return path.join('node_modules', '.bin', command);
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user