Compare commits

..

4 Commits

Author SHA1 Message Date
Nils Knappmeier ee913e28bd Added tests for multiple partial-block calls with inline partials
- nested inline partials with partial-blocks on different nesting levels
- nested inline partials (twice at each level)
2017-01-02 10:13:49 +01:00
Nils Knappmeier 7a77f61c44 Add more tests for different scenarios of using partial-blocks
- Multiple partial-blocks at different nesting levels
- Calling partial-blocks twice with nested partial-blocks
- Calling the partial-block from within the #each-helper
2017-01-02 10:05:21 +01:00
Nils Knappmeier 72753bcaa3 Possible fix for #1252: Refactoring for nested partial-block calls
This fix treats partial-blocks more like closures and uses the closure-context of
the "invokePartial"-function to store the @partial-block for the partial.
2017-01-01 08:45:59 +01:00
Nils Knappmeier f3d266a66e Test-case for #1252: Using @partial-block twice in a template not possible 2016-12-31 00:32:03 +01:00
26 changed files with 51 additions and 302 deletions
-6
View File
@@ -1,6 +0,0 @@
# Handlebars-template fixtures in test cases need deterministic eol
*.handlebars text eol=lf
*.hbs text eol=lf
# Lexer files as well
*.l text eol=lf
+1 -1
View File
@@ -1,2 +1,2 @@
instrumentation:
excludes: ['**/spec/**', '**/handlebars/compiler/parser.js']
excludes: ['**/spec/**']
+1 -1
View File
@@ -96,4 +96,4 @@ After this point the handlebars site needs to be updated to point to the new ver
[generator-release]: https://github.com/walmartlabs/generator-release
[pull-request]: https://github.com/wycats/handlebars.js/pull/new/master
[issue]: https://github.com/wycats/handlebars.js/issues/new
[jsfiddle]: https://jsfiddle.net/9D88g/113/
[jsfiddle]: https://jsfiddle.net/9D88g/47/
+1 -1
View File
@@ -1,4 +1,4 @@
Copyright (C) 2011-2017 by Yehuda Katz
Copyright (C) 2011-2016 by Yehuda Katz
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
-1
View File
@@ -1,5 +1,4 @@
[![Travis Build Status](https://img.shields.io/travis/wycats/handlebars.js/master.svg)](https://travis-ci.org/wycats/handlebars.js)
[![Appveyor Build Status](https://ci.appveyor.com/api/projects/status/github/wycats/handlebars.js?branch=master&svg=true)](https://ci.appveyor.com/project/wycats/handlebars-js)
[![Selenium Test Status](https://saucelabs.com/buildstatus/handlebars)](https://saucelabs.com/u/handlebars)
Handlebars.js
-38
View File
@@ -1,38 +0,0 @@
# Test against these versions of Node.js
environment:
matrix:
- nodejs_version: "4"
- nodejs_version: "5"
platform:
- x64
# Install scripts (runs after repo cloning)
install:
# Get the latest stable version of Node.js
- ps: Install-Product node $env:nodejs_version $env:platform
# Clone submodules (mustache spec)
- cmd: git submodule update --init --recursive
# Install modules
- cmd: npm install
- cmd: npm install -g grunt-cli
# Post-install test scripts
test_script:
# Output useful info for debugging
- cmd: node --version
- cmd: npm --version
# Run tests
- cmd: grunt --stack travis
# Don't actually build
build: off
on_failure:
- cmd: 7z a coverage.zip coverage
- cmd: appveyor PushArtifact coverage.zip
# Set build version format here instead of in the admin panel
version: "{build}"
+1 -1
View File
@@ -11,7 +11,7 @@ function BenchWarmer() {
this.errors = {};
}
var print = require('util').print;
var print = require('sys').print;
BenchWarmer.prototype = {
winners: function(benches) {
+1 -1
View File
@@ -1,6 +1,6 @@
{
"name": "handlebars",
"version": "4.0.11",
"version": "4.0.6",
"main": "handlebars.js",
"license": "MIT",
"dependencies": {}
+1 -1
View File
@@ -2,7 +2,7 @@
<package>
<metadata>
<id>handlebars.js</id>
<version>4.0.11</version>
<version>4.0.6</version>
<authors>handlebars.js Authors</authors>
<licenseUrl>https://github.com/wycats/handlebars.js/blob/master/LICENSE</licenseUrl>
<projectUrl>https://github.com/wycats/handlebars.js/</projectUrl>
+7 -29
View File
@@ -66,7 +66,7 @@ interface MustacheStatement <: Statement {
interface BlockStatement <: Statement {
type: "BlockStatement";
path: PathExpression | Literal;
path: PathExpression;
params: [ Expression ];
hash: Hash;
@@ -296,43 +296,21 @@ The `Handlebars.JavaScriptCompiler` object has a number of methods that may be c
- `initializeBuffer()`
Allows for buffers other than the default string buffer to be used. Generally needs to be paired with a custom `appendToBuffer` implementation.
### Example for the compiler api.
This example changes all lookups of properties are performed by a helper (`lookupLowerCase`) which looks for `test` if `{{Test}}` occurs in the template. This is just to illustrate how compiler behavior can be change.
There is also [a jsfiddle with this code](https://jsfiddle.net/9D88g/162/) if you want to play around with it.
```javascript
function MyCompiler() {
Handlebars.JavaScriptCompiler.apply(this, arguments);
}
MyCompiler.prototype = new Handlebars.JavaScriptCompiler();
MyCompiler.prototype = Object.create(Handlebars.JavaScriptCompiler);
// Use this compile to compile BlockStatment-Blocks
MyCompiler.prototype.compiler = MyCompiler
MyCompiler.prototype.nameLookup = function(parent, name, type) {
if (type === 'context') {
return this.source.functionCall('helpers.lookupLowerCase', '', [parent, JSON.stringify(name)])
MyCompiler.nameLookup = function(parent, name, type) {
if (type === 'partial') {
return 'MyPartialList[' + JSON.stringify(name) ']';
} else {
return Handlebars.JavaScriptCompiler.prototype.nameLookup.call(this, parent, name, type);
}
}
};
var env = Handlebars.create();
env.registerHelper('lookupLowerCase', function(parent, name) {
return parent[name.toLowerCase()]
})
env.JavaScriptCompiler = MyCompiler;
var template = env.compile('{{#each Test}} ({{Value}}) {{/each}}');
console.log(template({
test: [
{value: 'a'},
{value: 'b'},
{value: 'c'}
]
}));
env.compile('my template');
```
+1 -1
View File
@@ -4,7 +4,7 @@ import {registerDefaultHelpers} from './helpers';
import {registerDefaultDecorators} from './decorators';
import logger from './logger';
export const VERSION = '4.0.11';
export const VERSION = '4.0.6';
export const COMPILER_REVISION = 7;
export const REVISION_CHANGES = {
+2 -3
View File
@@ -1,7 +1,7 @@
/* eslint-disable new-cap */
import Exception from '../exception';
import {isArray, indexOf, extend} from '../utils';
import {isArray, indexOf} from '../utils';
import AST from './ast';
const slice = [].slice;
@@ -70,7 +70,7 @@ Compiler.prototype = {
for (let name in knownHelpers) {
/* istanbul ignore else */
if (name in knownHelpers) {
this.options.knownHelpers[name] = knownHelpers[name];
options.knownHelpers[name] = knownHelpers[name];
}
}
}
@@ -488,7 +488,6 @@ export function compile(input, options = {}, env) {
throw new Exception('You must pass a string or Handlebars AST to Handlebars.compile. You passed ' + input);
}
options = extend({}, options);
if (!('data' in options)) {
options.data = true;
}
@@ -987,7 +987,7 @@ JavaScriptCompiler.prototype = {
let params = [],
paramsInit = this.setupHelperArgs(name, paramSize, params, blockHelper);
let foundHelper = this.nameLookup('helpers', name, 'helper'),
callContext = this.aliasable(`${this.contextName(0)} != null ? ${this.contextName(0)} : (container.nullContext || {})`);
callContext = this.aliasable(`${this.contextName(0)} != null ? ${this.contextName(0)} : {}`);
return {
params: params,
+2 -5
View File
@@ -124,8 +124,6 @@ export function template(templateSpec, env) {
return obj;
},
// An empty object to use as replacement for null-contexts
nullContext: Object.seal({}),
noop: env.VM.noop,
compilerInfo: templateSpec.compiler
@@ -189,7 +187,7 @@ export function template(templateSpec, env) {
export function wrapProgram(container, i, fn, data, declaredBlockParams, blockParams, depths) {
function prog(context, options = {}) {
let currentDepths = depths;
if (depths && context != depths[0] && !(context === container.nullContext && depths[0] === null)) {
if (depths && context != depths[0]) {
currentDepths = [context].concat(depths);
}
@@ -237,8 +235,7 @@ export function invokePartial(partial, context, options) {
options.data = createFrame(options.data);
// Wrapper function to get access to currentPartialBlock from the closure
let fn = options.fn;
partialBlock = options.data['partial-block'] = function partialBlockWrapper(context, options = {}) {
partialBlock = options.data['partial-block'] = function partialBlockWrapper(context, options) {
// Restore the partial-block from the closure for the execution of the block
// i.e. the part inside the block of the partial call.
options.data = createFrame(options.data);
+11 -32
View File
@@ -4,7 +4,7 @@ import fs from 'fs';
import * as Handlebars from './handlebars';
import {basename} from 'path';
import {SourceMapConsumer, SourceNode} from 'source-map';
import uglify from 'uglify-js';
module.exports.loadTemplates = function(opts, callback) {
loadStrings(opts, function(err, strings) {
@@ -235,6 +235,7 @@ module.exports.cli = function(opts) {
}
}
if (opts.map) {
output.add('\n//# sourceMappingURL=' + opts.map + '\n');
}
@@ -243,7 +244,15 @@ module.exports.cli = function(opts) {
output.map = output.map + '';
if (opts.min) {
output = minify(output, opts.map);
output = uglify.minify(output.code, {
fromString: true,
outSourceMap: opts.map,
inSourceMap: JSON.parse(output.map)
});
if (opts.map) {
output.code += '\n//# sourceMappingURL=' + opts.map + '\n';
}
}
if (opts.map) {
@@ -265,33 +274,3 @@ function arrayCast(value) {
}
return value;
}
/**
* Run uglify to minify the compiled template, if uglify exists in the dependencies.
*
* We are using `require` instead of `import` here, because es6-modules do not allow
* dynamic imports and uglify-js is an optional dependency. Since we are inside NodeJS here, this
* should not be a problem.
*
* @param {string} output the compiled template
* @param {string} sourceMapFile the file to write the source map to.
*/
function minify(output, sourceMapFile) {
try {
// Try to resolve uglify-js in order to see if it does exist
require.resolve('uglify-js');
} catch (e) {
if (e.code !== 'MODULE_NOT_FOUND') {
// Something else seems to be wrong
throw e;
}
// it does not exist!
console.error('Code minimization is disabled due to missing uglify-js dependency');
return output;
}
return require('uglify-js').minify(output.code, {
fromString: true,
outSourceMap: sourceMapFile,
inSourceMap: JSON.parse(output.map)
});
}
+1 -1
View File
@@ -1,7 +1,7 @@
{
"name": "handlebars",
"barename": "handlebars",
"version": "4.0.11",
"version": "4.0.6",
"description": "Handlebars provides the power necessary to let you build semantic templates effectively with no frustration",
"homepage": "http://www.handlebarsjs.com/",
"keywords": [
+1 -55
View File
@@ -2,61 +2,7 @@
## Development
[Commits](https://github.com/wycats/handlebars.js/compare/v4.0.11...master)
## v4.0.11 - October 17th, 2017
- [#1391](https://github.com/wycats/handlebars.js/issues/1391) - `uglify-js` is unconditionally imported, but only listed as optional dependency ([@Turbo87](https://api.github.com/users/Turbo87))
- [#1233](https://github.com/wycats/handlebars.js/issues/1233) - Unable to build under windows - error at test:bin task ([@blikblum](https://api.github.com/users/blikblum))
- Update (C) year in the LICENSE file - 21386b6
Compatibility notes:
- This is a bugfix release. There are no breaking change and no new features.
[Commits](https://github.com/nknapp/handlebars.js/compare/v4.0.10...v4.0.11)
## v4.0.10 - May 21st, 2017
- Fix regression in 4.0.9: Replace "Object.assign" (not support in IE) by "util/extend" - 0e953d1
[Commits](https://github.com/nknapp/handlebars.js/compare/v4.0.9...v4.0.10)
## v4.0.9 - May 21st, 2017
- [#1327](https://github.com/wycats/handlebars.js/issues/1327) Handlebars.compile() does not modify "options" anymore
- pending [#1331](https://github.com/wycats/handlebars.js/issues/1331) Attempts to build Handlebars in a Windows environment
- Fix build in windows - cc554a5
- Ensure LF line-edings in handlebars-template fixtures (*.hbs) - ed879a6
- Run integration test with `node handlebars -a ...` on Windows - 2e21e2b
- Ensure LF line-edings in lexer-files (*.l) - bdfdbea
- Force LF line-endings for spec/artifacts - b50ef03
- Use istanbul/lib/cli.js instead of node_modules/.bin/istanbul - 6e6269f
- TravisCI: Publish valid semver tags independently of the branch - 7378f85
Compatibility notes:
- No compatibility issues are expected.
[Commits](https://github.com/nknapp/handlebars.js/compare/v4.0.8...v4.0.9)
## v4.0.8 - May 2nd, 2017
- [#1341](https://github.com/wycats/handlebars.js/issues/1341) [#1342](https://github.com/wycats/handlebars.js/issues/1342) Allow partial-blocks to be executed without "options" ([@nknapp](https://github.com/nknapp)) - a00c598
Compatibility notes:
- No breaking changes
[Commits](https://github.com/nknapp/handlebars.js/compare/v4.0.7...v4.0.8)
## v4.0.7 - April 29th, 2017
- [#1319](https://github.com/wycats/handlebars.js/issues/1319): Fix context-stack when calling block-helpers on null values ([@nknapp](https://github.com/nknapp)) - c8f4b57
- [#1315](https://github.com/wycats/handlebars.js/pull/1315) Parser: Change suffix to use ES6 default module export ([@Turbo87](https://github.com/Turbo87))- b617375
- [#1290](https://github.com/wycats/handlebars.js/pull/1290) [#1252](https://github.com/wycats/handlebars.js/issue/1290) Add more tests for partial-blocks and inline partials ([@nknapp](https://github.com/nknapp)) - 63a8e0c
- [#1252](https://github.com/wycats/handlebars.js/issue/1290) Using @partial-block twice in a template not possible ([@nknapp](https://github.com/nknapp)) - 5a164d0
- [#1310](https://github.com/wycats/handlebars.js/pull/1310) Avoid duplicate "sourceMappingURL=" lines. ([@joonas-lahtinen](https://github.com/joonas-lahtinen)) - 01b0f65
- [#1275](https://github.com/wycats/handlebars.js/pull/1275) require('sys') is deprecated, using 'util' instead ([@travnels](https://github.com/travnels)) - 406f2ee
- [#1285](https://github.com/wycats/handlebars.js/pull/1285) [#1284](https://github.com/wycats/handlebars.js/issues/1284) Make "column"-property of Errors enumerable ([@nknapp](https://github.com/nknapp)) - a023cb4
- [#1285](https://github.com/wycats/handlebars.js/pull/1285) Testcase to verify that compile-errors have a column-property ([@nknapp](https://github.com/nknapp)) - c7dc353
[Commits](https://github.com/lawnsea/handlebars.js/compare/v4.0.6...v4.0.7)
[Commits](https://github.com/lawnsea/handlebars.js/compare/v4.0.6...master)
## v4.0.6 - November 12th, 2016
- [#1243](https://github.com/wycats/handlebars.js/pull/1243) - Walk up data frames for nested @partial-block ([@lawnsea](https://github.com/lawnsea))
-12
View File
@@ -73,18 +73,6 @@ describe('compiler', function() {
it('can pass through an empty string', function() {
equal(Handlebars.compile('')(), '');
});
it('should not modify the options.data property(GH-1327)', function() {
var options = {data: [{a: 'foo'}, {a: 'bar'}]};
Handlebars.compile('{{#each data}}{{@index}}:{{a}} {{/each}}', options)();
equal(JSON.stringify(options, 0, 2), JSON.stringify({data: [{a: 'foo'}, {a: 'bar'}]}, 0, 2));
});
it('should not modify the options.knownHelpers property(GH-1327)', function() {
var options = {knownHelpers: {}};
Handlebars.compile('{{#each data}}{{@index}}:{{a}} {{/each}}', options)();
equal(JSON.stringify(options, 0, 2), JSON.stringify({knownHelpers: {}}, 0, 2));
});
});
describe('#precompile', function() {
+1 -2
View File
@@ -9,8 +9,7 @@ var filename = 'dist/handlebars.js';
if (global.minimizedTest) {
filename = 'dist/handlebars.min.js';
}
var distHandlebars = fs.readFileSync(require.resolve(`../../${filename}`), 'utf-8');
vm.runInThisContext(distHandlebars, filename);
vm.runInThisContext(fs.readFileSync(__dirname + '/../../' + filename), filename);
global.CompilerContext = {
browser: true,
+1 -1
View File
@@ -15,7 +15,7 @@ if (grep === '--min') {
var files = fs.readdirSync(testDir)
.filter(function(name) { return (/.*\.js$/).test(name); })
.map(function(name) { return testDir + path.sep + name; });
.map(function(name) { return testDir + '/' + name; });
if (global.minimizedTest) {
run('./runtime', function() {
+2 -63
View File
@@ -12,8 +12,6 @@ describe('precompiler', function() {
var log,
logFunction,
errorLog,
errorLogFunction,
precompile,
minify,
@@ -28,51 +26,16 @@ describe('precompiler', function() {
content,
writeFileSync;
/**
* Mock the Module.prototype.require-function such that an error is thrown, when "uglify-js" is loaded.
*
* The function cleans up its mess when "callback" is finished
*
* @param {Error} loadError the error that should be thrown if uglify is loaded
* @param {function} callback a callback-function to run when the mock is active.
*/
function mockRequireUglify(loadError, callback) {
var Module = require('module');
var _resolveFilename = Module._resolveFilename;
delete require.cache[require.resolve('uglify-js')];
delete require.cache[require.resolve('../dist/cjs/precompiler')];
Module._resolveFilename = function(request, mod) {
if (request === 'uglify-js') {
throw loadError;
}
return _resolveFilename.call(this, request, mod);
};
try {
callback();
} finally {
Module._resolveFilename = _resolveFilename;
delete require.cache[require.resolve('uglify-js')];
delete require.cache[require.resolve('../dist/cjs/precompiler')];
}
}
beforeEach(function() {
precompile = Handlebars.precompile;
minify = uglify.minify;
writeFileSync = fs.writeFileSync;
// Mock stdout and stderr
logFunction = console.log;
log = '';
console.log = function() {
log += Array.prototype.join.call(arguments, '');
};
errorLogFunction = console.error;
errorLog = '';
console.error = function() {
errorLog += Array.prototype.join.call(arguments, '');
};
fs.writeFileSync = function(_file, _content) {
file = _file;
content = _content;
@@ -83,7 +46,6 @@ describe('precompiler', function() {
uglify.minify = minify;
fs.writeFileSync = writeFileSync;
console.log = logFunction;
console.error = errorLogFunction;
});
it('should output version', function() {
@@ -186,41 +148,18 @@ describe('precompiler', function() {
equal(log, 'min');
});
it('should omit minimization gracefully, if uglify-js is missing', function() {
var error = new Error("Cannot find module 'uglify-js'");
error.code = 'MODULE_NOT_FOUND';
mockRequireUglify(error, function() {
var Precompiler = require('../dist/cjs/precompiler');
Handlebars.precompile = function() { return 'amd'; };
Precompiler.cli({templates: [emptyTemplate], min: true});
equal(/template\(amd\)/.test(log), true);
equal(/\n/.test(log), true);
equal(/Code minimization is disabled/.test(errorLog), true);
});
});
it('should fail on errors (other than missing module) while loading uglify-js', function() {
mockRequireUglify(new Error('Mock Error'), function() {
shouldThrow(function() {
var Precompiler = require('../dist/cjs/precompiler');
Handlebars.precompile = function() { return 'amd'; };
Precompiler.cli({templates: [emptyTemplate], min: true});
}, Error, 'Mock Error');
});
});
it('should output map', function() {
Precompiler.cli({templates: [emptyTemplate], map: 'foo.js.map'});
equal(file, 'foo.js.map');
equal(log.match(/sourceMappingURL=/g).length, 1);
equal(/sourceMappingURL=/.test(log), true);
});
it('should output map', function() {
Precompiler.cli({templates: [emptyTemplate], min: true, map: 'foo.js.map'});
equal(file, 'foo.js.map');
equal(log.match(/sourceMappingURL=/g).length, 1);
equal(/sourceMappingURL=/.test(log), true);
});
describe('#loadTemplates', function() {
-14
View File
@@ -277,18 +277,4 @@ describe('Regressions', function() {
shouldCompileTo(string, { listOne: ['a'], listTwo: ['b']}, 'ab', '');
});
it('GH-1319: "unless" breaks when "each" value equals "null"', function() {
var string = '{{#each list}}{{#unless ./prop}}parent={{../value}} {{/unless}}{{/each}}';
shouldCompileTo(string, { value: 'parent', list: [ null, 'a'] }, 'parent=parent parent=parent ', '');
});
it('GH-1341: 4.0.7 release breaks {{#if @partial-block}} usage', function() {
var string = 'template {{>partial}} template';
var partials = {
partialWithBlock: '{{#if @partial-block}} block {{> @partial-block}} block {{/if}}',
partial: '{{#> partialWithBlock}} partial {{/partialWithBlock}}'
};
shouldCompileToWithPartials(string, [{}, {}, partials], true, 'template block partial block template');
});
});
+1 -1
View File
@@ -1 +1 @@
// File ignored in coverage tests via setting in .istanbul.yml
/* istanbul ignore next */
+2 -1
View File
@@ -1 +1,2 @@
export default handlebars;
exports.__esModule = true;
exports['default'] = handlebars;
+6 -14
View File
@@ -15,22 +15,14 @@ module.exports = function(grunt) {
git.commitInfo(function(err, info) {
grunt.log.writeln('tag: ' + info.tagName);
var files = [];
// Publish the master as "latest" and with the commit-id
if (info.isMaster) {
files.push('-latest');
files.push('-' + info.head);
}
// Publish tags by their tag-name
if (info.tagName && semver.valid(info.tagName)) {
files.push('-' + info.tagName);
}
if (files.length > 0) {
initSDK();
grunt.log.writeln('publishing files: ' + JSON.stringify(files));
var files = ['-latest', '-' + info.head];
if (info.tagName && semver.valid(info.tagName)) {
files.push('-' + info.tagName);
}
publish(fileMap(files), done);
} else {
// Silently ignore for branches
+6 -16
View File
@@ -1,27 +1,17 @@
var childProcess = require('child_process'),
fs = require('fs'),
os = require('os');
fs = require('fs');
module.exports = function(grunt) {
grunt.registerTask('test:bin', function() {
var done = this.async();
var cmd = './bin/handlebars';
var args = [ '-a', 'spec/artifacts/empty.handlebars' ];
// On Windows, the executable handlebars.js file cannot be run directly
if (os.platform() === 'win32') {
args.unshift(cmd);
cmd = process.argv[0];
}
childProcess.execFile(cmd, args, function(err, stdout) {
childProcess.exec('./bin/handlebars -a spec/artifacts/empty.handlebars', function(err, stdout) {
if (err) {
throw err;
}
var expected = fs.readFileSync('./spec/expected/empty.amd.js').toString().replace(/\r\n/g, '\n');
if (stdout.toString() !== expected) {
var expected = fs.readFileSync('./spec/expected/empty.amd.js');
if (stdout.toString() !== expected.toString()) {
throw new Error('Expected binary output differed:\n\n"' + stdout + '"\n\n"' + expected + '"');
}
@@ -42,7 +32,7 @@ module.exports = function(grunt) {
grunt.registerTask('test:cov', function() {
var done = this.async();
var runner = childProcess.fork('node_modules/istanbul/lib/cli.js', ['cover', '--source-map', '--', './spec/env/runner.js'], {stdio: 'inherit'});
var runner = childProcess.fork('node_modules/.bin/istanbul', ['cover', '--source-map', '--', './spec/env/runner.js'], {stdio: 'inherit'});
runner.on('close', function(code) {
if (code != 0) {
grunt.fatal(code + ' tests failed');
@@ -65,7 +55,7 @@ module.exports = function(grunt) {
grunt.registerTask('test:check-cov', function() {
var done = this.async();
var runner = childProcess.fork('node_modules/istanbul/lib/cli.js', ['check-coverage', '--statements', '100', '--functions', '100', '--branches', '100', '--lines 100'], {stdio: 'inherit'});
var runner = childProcess.fork('node_modules/.bin/istanbul', ['check-coverage', '--statements', '100', '--functions', '100', '--branches', '100', '--lines 100'], {stdio: 'inherit'});
runner.on('close', function(code) {
if (code != 0) {
grunt.fatal('Coverage check failed: ' + code);