@samitouri / QOS-React-2 / commits / 1511fff598

eslint

chico committed Feb 12, 2015 at 23:48 UTC 1511fff5982cb3a0557a59b5840ac295de3402a5
51 files changed +878 -642
.eslintignore
+1
@@ -7,3 +7,4 @@ src/vendor_deprecated
7 src/**/__tests__/**
8 # This should be enabled but that folder has too much in it that doesn't belong
9 src/test
10 +test/the-files-to-test.generated.js
\ No newline at end of file
.eslintrc new
+50
@@ -0,0 +1,50 @@
1 +---
2 +parser: esprima-fb
3 +
4 +env:
5 + browser: true
6 + node: true
7 +
8 +globals:
9 + __DEV__: true
10 +
11 +rules:
12 + # ERRORS
13 + space-before-blocks: [2, 'always']
14 + brace-style: 2
15 + space-after-keywords: 2
16 + strict: 2
17 + # We actually have a transform to support this and we fix this for bundled
18 + # releases but not for the npm package, so enforce it strictly
19 + no-comma-dangle: 2
20 + # Make this a warning for now. We do this in a few places so we might need to
21 + # disable
22 + no-unused-expressions: 2
23 + block-scoped-var: 2
24 + eol-last: 2
25 + dot-notation: 2
26 + consistent-return: 2
27 + no-unused-vars: [2, args: none]
28 + quotes: [2, 'single']
29 +
30 + # WARNINGS
31 + # This is the only one that's hard to track since we don't lint just changes.
32 + max-len: [1, 80]
33 +
34 + # WISHLIST. One day...
35 + # We'll need a custom version of this that does a subset of the whole rule.
36 + # Otherwise this is just too noisy.
37 + # valid-jsdoc: 1
38 +
39 + # DISABLED. These aren't compatible with our style
40 + # We use this for private/internal variables
41 + no-underscore-dangle: 0
42 + # We pass constructors around / access them from members
43 + new-cap: 0
44 + # We do this a lot.
45 + no-use-before-define: 0
46 + # We do this in a few places to align values
47 + key-spacing: 0
48 +
49 + # DISABLED. These currently cause errors when running.
50 + no-multi-spaces: 0
.jshintrc deleted
-18
@@ -1,18 +0,0 @@
1 -{
2 - "node": true,
3 -
4 - "boss": true,
5 - "curly": true,
6 - "devel": true,
7 - "eqnull": true,
8 - "expr": true,
9 - "funcscope": true,
10 - "globalstrict": true,
11 - "loopfunc": true,
12 - "newcap": false,
13 - "noempty": true,
14 - "nonstandard": true,
15 - "sub": true,
16 - "undef": true,
17 - "unused": "vars"
18 -}
Gruntfile.js
+58 -35
@@ -12,6 +12,7 @@ var npmReactTasks = require('./grunt/tasks/npm-react');
12 var npmReactToolsTasks = require('./grunt/tasks/npm-react-tools');
13 var versionCheckTask = require('./grunt/tasks/version-check');
14 var gemReactSourceTasks = require('./grunt/tasks/gem-react-source');
15 +var eslintTask = require('./grunt/tasks/eslint');
16
17 module.exports = function(grunt) {
18
@@ -22,45 +23,43 @@ module.exports = function(grunt) {
23 browserify: require('./grunt/config/browserify'),
24 populist: require('./grunt/config/populist')(grunt),
25 connect: require('./grunt/config/server')(grunt),
25 - "webdriver-jasmine": require('./grunt/config/webdriver-jasmine'),
26 - "webdriver-perf": require('./grunt/config/webdriver-perf'),
26 + 'webdriver-jasmine': require('./grunt/config/webdriver-jasmine'),
27 + 'webdriver-perf': require('./grunt/config/webdriver-perf'),
28 npm: require('./grunt/config/npm'),
28 - clean: ['./build', './*.gem', './docs/_site', './examples/shared/*.js', '.module-cache'],
29 + clean: [
30 + './build',
31 + './*.gem',
32 + './docs/_site',
33 + './examples/shared/*.js',
34 + '.module-cache'
35 + ],
36 jshint: require('./grunt/config/jshint'),
37 + /*eslint-disable camelcase */
38 compare_size: require('./grunt/config/compare_size')
39 + /*eslint-enable camelcase */
40 });
41
42 grunt.config.set('compress', require('./grunt/config/compress'));
43
44 Object.keys(grunt.file.readJSON('package.json').devDependencies)
36 - .filter(function(npmTaskName) { return npmTaskName.indexOf('grunt-') === 0; })
37 - .filter(function(npmTaskName) { return npmTaskName != 'grunt-cli'; })
38 - .forEach(function(npmTaskName) { grunt.loadNpmTasks(npmTaskName); });
39 -
40 - // Super simplified eslint task that we can use to replace linting. This just
41 - // shells out to eslint.
42 - grunt.registerTask('eslint', function() {
43 - var done = this.async();
44 - grunt.util.spawn({
45 - cmd: 'node_modules/.bin/eslint',
46 - args: ['src']
47 - }, function(err, result, code) {
48 - if (code === 0) {
49 - grunt.log.ok('Lint passed (but may contain warnings)');
50 - } else {
51 - grunt.log.error('Lint failed');
52 - }
53 - if (result.stdout.length) {
54 - grunt.log.writeln(result.stdout);
55 - }
56 -
57 - done(code === 0);
45 + .filter(function(npmTaskName) {
46 + return npmTaskName.indexOf('grunt-') === 0;
47 + })
48 + .filter(function(npmTaskName) {
49 + return npmTaskName !== 'grunt-cli';
50 + })
51 + .forEach(function(npmTaskName) {
52 + grunt.loadNpmTasks(npmTaskName);
53 });
59 - });
54 +
55 + grunt.registerTask('eslint', eslintTask);
56
57 grunt.registerTask('lint', ['eslint']);
58
63 - grunt.registerTask('download-previous-version', require('./grunt/tasks/download-previous-version.js'));
59 + grunt.registerTask(
60 + 'download-previous-version',
61 + require('./grunt/tasks/download-previous-version.js')
62 + );
63
64 grunt.registerTask('delete-build-modules', function() {
65 if (grunt.file.exists('build/modules')) {
@@ -93,11 +92,28 @@ module.exports = function(grunt) {
92
93 grunt.registerTask('version-check', versionCheckTask);
94
96 - grunt.registerTask('build:basic', ['jsx:normal', 'version-check', 'browserify:basic']);
97 - grunt.registerTask('build:addons', ['jsx:normal', 'browserify:addons']);
98 - grunt.registerTask('build:transformer', ['jsx:normal', 'browserify:transformer']);
99 - grunt.registerTask('build:min', ['jsx:normal', 'version-check', 'browserify:min']);
100 - grunt.registerTask('build:addons-min', ['jsx:normal', 'browserify:addonsMin']);
95 + grunt.registerTask('build:basic', [
96 + 'jsx:normal',
97 + 'version-check',
98 + 'browserify:basic'
99 + ]);
100 + grunt.registerTask('build:addons', [
101 + 'jsx:normal',
102 + 'browserify:addons'
103 + ]);
104 + grunt.registerTask('build:transformer', [
105 + 'jsx:normal',
106 + 'browserify:transformer'
107 + ]);
108 + grunt.registerTask('build:min', [
109 + 'jsx:normal',
110 + 'version-check',
111 + 'browserify:min'
112 + ]);
113 + grunt.registerTask('build:addons-min', [
114 + 'jsx:normal',
115 + 'browserify:addonsMin'
116 + ]);
117 grunt.registerTask('build:withCodeCoverageLogging', [
118 'jsx:normal',
119 'version-check',
@@ -117,8 +133,15 @@ module.exports = function(grunt) {
133 'version-check',
134 'populist:test'
135 ]);
120 - grunt.registerTask('build:npm-react', ['version-check', 'jsx:normal', 'npm-react:release']);
121 - grunt.registerTask('build:gem-react-source', ['build', 'gem-react-source:release']);
136 + grunt.registerTask('build:npm-react', [
137 + 'version-check',
138 + 'jsx:normal',
139 + 'npm-react:release'
140 + ]);
141 + grunt.registerTask('build:gem-react-source', [
142 + 'build',
143 + 'gem-react-source:release'
144 + ]);
145
146 grunt.registerTask('webdriver-phantomjs', webdriverPhantomJSTask);
147
@@ -161,7 +184,7 @@ module.exports = function(grunt) {
184 'webdriver-perf:saucelabs_firefox',
185 'webdriver-perf:saucelabs_chrome',
186 'webdriver-perf:saucelabs_ie11',
164 - 'webdriver-perf:saucelabs_ie8',
187 + 'webdriver-perf:saucelabs_ie8'
188 ]);
189
190 grunt.registerTask('test:webdriver:saucelabs', [
README.md
+1 -1
@@ -86,7 +86,7 @@ grunt test
86 grunt test --debug
87 # For speed, you can use fasttest and add --filter to only run one test
88 grunt fasttest --filter=ReactIdentity
89 -# Lint the code with JSHint
89 +# Lint the code with ESLint
90 grunt lint
91 # Wipe out build directory
92 grunt clean
grunt/config/browserify.js
+1 -2
@@ -1,5 +1,4 @@
1 -/* jshint multistr:true */
2 -/* jshint -W040 */
1 +/*eslint-disable no-multi-str */
2
3 'use strict';
4
grunt/config/compare_size.js
+1 -1
@@ -12,6 +12,6 @@ module.exports = {
12 return gzip.zip(contents, {}).length;
13 }
14 },
15 - cache: ".grunt/sizecache.json"
15 + cache: '.grunt/sizecache.json'
16 }
17 };
grunt/config/copy.js
+1 -1
@@ -1,5 +1,5 @@
1 'use strict';
2 -
2 +/*eslint-disable camelcase*/
3 module.exports = {
4
5 react_docs: {
grunt/config/jsx.js
+11 -11
@@ -4,15 +4,15 @@ var grunt = require('grunt');
4 var _ = require('lodash');
5
6 var rootIDs = [
7 - "React",
8 - "ReactWithAddons"
7 + 'React',
8 + 'ReactWithAddons'
9 ];
10
11 // TODO: stop packaging these libraries
12 rootIDs = rootIDs.concat([
13 - "merge",
14 - "mergeInto",
15 - "copyProperties"
13 + 'merge',
14 + 'mergeInto',
15 + 'copyProperties'
16 ]);
17
18 var normal = {
@@ -23,23 +23,23 @@ var normal = {
23 constants: {}
24 };
25 },
26 - sourceDir: "src",
27 - outputDir: "build/modules"
26 + sourceDir: 'src',
27 + outputDir: 'build/modules'
28 };
29
30
31 var test = {
32 rootIDs: rootIDs.concat([
33 - "test/all.js",
34 - "**/__tests__/*.js"
33 + 'test/all.js',
34 + '**/__tests__/*.js'
35 ]),
36 getConfig: function() {
37 return _.merge({}, normal.getConfig(), {
38 mocking: true
39 });
40 },
41 - sourceDir: "src",
42 - outputDir: "build/modules"
41 + sourceDir: 'src',
42 + outputDir: 'build/modules'
43 };
44
45
grunt/config/populist.js
+7 -7
@@ -2,12 +2,12 @@
2
3 module.exports = function(grunt) {
4 var jasmine = {
5 - rootDirectory: "build/jasmine",
6 - // This syntax means to require and expose the "jasmine" module
5 + rootDirectory: 'build/jasmine',
6 + // This syntax means to require and expose the 'jasmine' module
7 // (build/jasmine/jasmine.js) as global.jasmine, and to require the
8 - // "all" module (build/jasmine/all.js) but not expose it globally.
9 - args: ["jasmine:jasmine", "all:"],
10 - outfile: "./build/jasmine.js"
8 + // 'all' module (build/jasmine/all.js) but not expose it globally.
9 + args: ['jasmine:jasmine', 'all:'],
10 + outfile: './build/jasmine.js'
11 };
12
13 var filterExpr = grunt.option('filter');
@@ -19,8 +19,8 @@ module.exports = function(grunt) {
19 }
20
21 var test = {
22 - rootDirectory: "build/modules",
23 - args: ["test/all:harness"],
22 + rootDirectory: 'build/modules',
23 + args: ['test/all:harness'],
24 requires: [filterExpr],
25 outfile: './build/react-test.js'
26 };
grunt/config/server.js
+24 -17
@@ -1,9 +1,12 @@
1 'use strict';
2
3 -module.exports = function(grunt){
3 +var fs = require('fs');
4 +var path = require('path');
5 +
6 +module.exports = function(grunt) {
7 var coverageWriteStream;
8
6 - grunt.task.registerTask('finalize-coverage-stream', function(){
9 + grunt.task.registerTask('finalize-coverage-stream', function() {
10 if (!coverageWriteStream) {
11 return;
12 }
@@ -14,13 +17,13 @@ module.exports = function(grunt){
17 });
18
19 function consoleLoggerMiddleware(req, res, next) {
17 - if (!(req.method == 'POST' && req._parsedUrl.pathname.replace(/\//g,'') == 'console' && Array.isArray(req.body))) {
20 + if (!(req.method === 'POST' && req._parsedUrl.pathname.replace(/\//g, '') === 'console' && Array.isArray(req.body))) {
21 return next();
22 }
23 res.write('<!doctype html><meta charset=utf-8>');
24 res.end('Got it, thanks!');
25
23 - req.body.forEach(function(log){
26 + req.body.forEach(function(log) {
27 if (log.message.indexOf('not ok ') === 0) {
28 log.type = 'error';
29 } else if (log.message.indexOf('ok ') === 0) {
@@ -31,20 +34,20 @@ module.exports = function(grunt){
34 log.type = 'coverage done';
35 }
36
34 - if (log.type == 'error') {
37 + if (log.type === 'error') {
38 grunt.log.error(log.message);
36 - } else if (log.type == 'ok') {
39 + } else if (log.type === 'ok') {
40 grunt.log.ok(log.message);
38 - } else if (log.type == 'log') {
41 + } else if (log.type === 'log') {
42 grunt.log.writeln(log.message);
40 - } else if (log.type == 'coverage') {
43 + } else if (log.type === 'coverage') {
44 if (!coverageWriteStream) {
42 - coverageWriteStream = require('fs').createWriteStream(__dirname + '/../../coverage.log');
45 + coverageWriteStream = fs.createWriteStream(path.join(__dirname, '/../../coverage.log'));
46 }
47 coverageWriteStream.write(log.message + '\n');
45 - } else if (log.type == 'coverage done') {
48 + } else if (log.type === 'coverage done') {
49 grunt.task.run('finalize-coverage-stream');
47 - } else if (log.type == 'perf') {
50 + } else if (log.type === 'perf') {
51 grunt.event.emit('perf results', log.message);
52 } else {
53 grunt.verbose.writeln(log);
@@ -53,7 +56,7 @@ module.exports = function(grunt){
56 }
57
58 function testResultLoggerMiddleware(req, res, next) {
56 - if (!(req.method == 'POST' && req._parsedUrl.pathname.indexOf('/reportTestResults') === 0)) {
59 + if (!(req.method === 'POST' && req._parsedUrl.pathname.indexOf('/reportTestResults') === 0)) {
60 return next();
61 }
62 res.write('<!doctype html><meta charset=utf-8>');
@@ -62,8 +65,8 @@ module.exports = function(grunt){
65 var logType = 'writeln';
66 var message = req.body;
67
65 - if (req.body.type && req.body.message){
66 - if (req.body.type == 'error') {
68 + if (req.body.type && req.body.message) {
69 + if (req.body.type === 'error') {
70 logType = 'error';
71 } else if (req.body.message.indexOf('ok') === 0) {
72 logType = 'ok';
@@ -72,7 +75,7 @@ module.exports = function(grunt){
75 }
76 message = req.body.message;
77 }
75 - if (typeof message != 'string') {
78 + if (typeof message !== 'string') {
79 message = JSON.stringify(message, null, 2);
80 }
81 grunt.log[logType]('[%s][%s]', req.headers['user-agent'], Date.now(), message);
@@ -86,8 +89,12 @@ module.exports = function(grunt){
89 port: 9999,
90 middleware: function(connect, options) {
91
89 - connect.logger.token('user-agent', function(req, res) { return req.headers['user-agent']; });
90 - connect.logger.token('timestamp', function(req, res) { return Date.now(); });
92 + connect.logger.token('user-agent', function(req, res) {
93 + return req.headers['user-agent'];
94 + });
95 + connect.logger.token('timestamp', function(req, res) {
96 + return Date.now();
97 + });
98
99 return [
100 connect.json(),
grunt/config/webdriver-all.js
+17 -15
@@ -2,20 +2,20 @@
2
3 var grunt = require('grunt');
4
5 -module.exports = function(props){
6 - if (typeof props.url != 'string') {
5 +module.exports = function(props) {
6 + if (typeof props.url !== 'string') {
7 throw TypeError('expected url string');
8 }
9 - if ('isDoneTimeout' in props && typeof props.isDoneTimeout != 'number') {
9 + if ('isDoneTimeout' in props && typeof props.isDoneTimeout !== 'number') {
10 throw TypeError('expected isDoneTimeout to be a number');
11 }
12 - if ('onStart' in props && typeof props.onStart != 'function') {
12 + if ('onStart' in props && typeof props.onStart !== 'function') {
13 throw TypeError('expected onStart to be a function');
14 }
15 - if ('onComplete' in props && typeof props.onComplete != 'function') {
15 + if ('onComplete' in props && typeof props.onComplete !== 'function') {
16 throw TypeError('expected onComplete to be a function');
17 }
18 - if ('onError' in props && typeof props.onError != 'function') {
18 + if ('onError' in props && typeof props.onError !== 'function') {
19 throw TypeError('expected onError to be a function');
20 }
21
@@ -33,7 +33,7 @@ module.exports = function(props){
33 };
34
35 if (grunt.option('debug')) {
36 - exports.local.url += (exports.local.url.indexOf('?') == -1 ? '?' : '&') + 'debug=' + grunt.option('debug');
36 + exports.local.url += (exports.local.url.indexOf('?') === -1 ? '?' : '&') + 'debug=' + grunt.option('debug');
37 }
38
39 exports.saucelabs = {
@@ -49,13 +49,13 @@ module.exports = function(props){
49 }
50 },
51 desiredCapabilities: {
52 - "build": process.env.TRAVIS_BUILD_NUMBER || 'dev' + Date.now(),
53 - "tunnel-identifier": process.env.TRAVIS_JOB_NUMBER || 'my awesome tunnel',
54 - "browserName": "chrome"
52 + 'build': process.env.TRAVIS_BUILD_NUMBER || 'dev' + Date.now(),
53 + 'tunnel-identifier': process.env.TRAVIS_JOB_NUMBER || 'my awesome tunnel',
54 + 'browserName': 'chrome'
55 },
56 url: exports.local.url,
57 - onStart: function(browser){
58 - grunt.log.writeln("Starting WebDriver Test. Watch results here: http://saucelabs.com/tests/" + browser.sessionID);
57 + onStart: function(browser) {
58 + grunt.log.writeln('Starting WebDriver Test. Watch results here: http://saucelabs.com/tests/' + browser.sessionID);
59 if (props.onStart) {
60 return props.onStart(browser);
61 }
@@ -65,6 +65,7 @@ module.exports = function(props){
65 isDoneTimeout: exports.local.isDoneTimeout
66 };
67
68 + /*eslint-disable camelcase*/
69 /* https://saucelabs.com/platforms */
70 exports.saucelabs_ios =
71 exports.saucelabs_ios7 = sauceItUp({ browserName: 'iphone', version: '7', platform:'OS X 10.9' });
@@ -94,10 +95,11 @@ module.exports = function(props){
95 exports.saucelabs_ie9 = sauceItUp({ browserName: 'internet explorer', version: 9 });
96 exports.saucelabs_ie10 = sauceItUp({ browserName: 'internet explorer', version: 10 });
97 exports.saucelabs_ie11 = sauceItUp({ browserName: 'internet explorer', version: 11, platform:'Windows 8.1' });
98 + /*eslint-enable camelcase*/
99
100 function sauceItUp(desiredCapabilities) {
99 - desiredCapabilities["build"] = exports.saucelabs.desiredCapabilities["build"];
100 - desiredCapabilities["tunnel-identifier"] = exports.saucelabs.desiredCapabilities["tunnel-identifier"];
101 + desiredCapabilities.build = exports.saucelabs.desiredCapabilities.build;
102 + desiredCapabilities['tunnel-identifier'] = exports.saucelabs.desiredCapabilities['tunnel-identifier'];
103 return {
104 webdriver: exports.saucelabs.webdriver,
105 url: exports.saucelabs.url,
@@ -105,7 +107,7 @@ module.exports = function(props){
107 onComplete: exports.saucelabs.onComplete,
108 onError: exports.saucelabs.onError,
109 isDoneTimeout: exports.saucelabs.isDoneTimeout,
108 - desiredCapabilities: desiredCapabilities,
110 + desiredCapabilities: desiredCapabilities
111 };
112 }
113
grunt/config/webdriver-jasmine.js
+5 -5
@@ -3,13 +3,13 @@
3 var grunt = require('grunt');
4
5 module.exports = require('./webdriver-all')({
6 - url: "http://127.0.0.1:9999/test/index.html",
7 - onComplete: function(passed){
8 - if (!passed){
9 - grunt.fatal("tests failed");
6 + url: 'http://127.0.0.1:9999/test/index.html',
7 + onComplete: function(passed) {
8 + if (!passed) {
9 + grunt.fatal('tests failed');
10 }
11 },
12 - onError: function(error){
12 + onError: function(error) {
13 grunt.fatal(error);
14 }
15 });
grunt/config/webdriver-perf.js
+16 -9
@@ -1,8 +1,9 @@
1 'use strict';
2
3 var grunt = require('grunt');
4 +var path = require('path');
5
5 -var tests = grunt.file.expand(__dirname + '/../../perf/tests/*');
6 +var tests = grunt.file.expand(path.join(__dirname, '/../../perf/tests/*'));
7
8 var maxTime = 5;
9
@@ -15,33 +16,39 @@ var params = []
16 .concat('headless=false')
17 .concat('maxTime=' + maxTime)
18 .concat(tests
18 - .map(function(path){ return path.split(/tests./i).reverse()[0]; })
19 + .map(function(testPath) {
20 + return testPath.split(/tests./i).reverse()[0];
21 + })
22 .map(encodeURIComponent)
20 - .map(function(filename){ return 'test=' + filename; })
23 + .map(function(filename) {
24 + return 'test=' + filename;
25 + })
26 )
27 .concat(reactVersions
28 .map(encodeURIComponent)
24 - .map(function(version){ return 'react=' + version; }
29 + .map(function(version) {
30 + return 'react=' + version;
31 + }
32 )
33 );
34
35 module.exports = require('./webdriver-all')({
36
30 - url: "http://127.0.0.1:9999/perf/index.html?" + params.join('&'),
37 + url: 'http://127.0.0.1:9999/perf/index.html?' + params.join('&'),
38
39 isDoneTimeout: 15 * 60 * 1000,
40
34 - onStart: function(){
35 - grunt.event.on('perf results', function(results){
41 + onStart: function() {
42 + grunt.event.on('perf results', function(results) {
43 console.log(results);
44 });
45 },
46
40 - onComplete: function(completedTestKeys){
47 + onComplete: function(completedTestKeys) {
48 grunt.verbose.writeln('onComplete ' + JSON.stringify(completedTestKeys));
49 },
50
44 - onError: function(error){
51 + onError: function(error) {
52 grunt.fatal(error);
53 }
54
grunt/tasks/coverage-parse.js
+20 -19
@@ -1,47 +1,48 @@
1 -"use strict";
1 +'use strict';
2 var grunt = require('grunt');
3 +var path = require('path');
4 +var fs = require('fs');
5
4 -module.exports = function(){
5 - var ROOT = require('path').normalize(__dirname + '/../..');
6 +module.exports = function() {
7 + var ROOT = path.join(__dirname, '/../..');
8 var done = this.async();
9 var uncoveredExpressionCount = 0;
10 var uncoveredLineCount = 0;
11
10 - require('fs').createReadStream(ROOT + '/coverage.log')
11 - .pipe(require('coverify/parse')(function(error, results){
12 + fs.createReadStream(ROOT + '/coverage.log')
13 + .pipe(require('coverify/parse')(function(error, results) {
14 if (error) {
15 grunt.fatal(error);
16 }
17
18 Object.keys(results)
17 - .sort(function(a, b){
19 + .sort(function(a, b) {
20 return results[a].length - results[b].length;
21 })
22 .reverse()
21 - .forEach(function(path){
22 - if (results[path].length === 0) {
23 + .forEach(function(concretePath) {
24 + if (results[concretePath].length === 0) {
25 return;
26 }
25 - var relativePath = path.replace(ROOT, '');
26 - uncoveredExpressionCount += results[path].length;
27 - grunt.log.error(results[path].length + ' expressions not covered ' + relativePath);
27 + var relativePath = concretePath.replace(ROOT, '');
28 + uncoveredExpressionCount += results[concretePath].length;
29 + grunt.log.error(results[concretePath].length + ' expressions not covered ' + relativePath);
30
29 - results[path].forEach(function(c){
31 + results[concretePath].forEach(function(c) {
32 uncoveredLineCount += c.code.split('\n').length;
31 - console.log('txmt://open?url=' + encodeURIComponent('file://' + path) + '&line=' + (c.lineNum+1) + '&column=' + (c.column[0]+2));
33 + console.log('txmt://open?url=' + encodeURIComponent('file://' + concretePath) + '&line=' + (c.lineNum + 1) + '&column=' + (c.column[0] + 2));
34 });
35 console.log('');
34 - })
35 - ;
36 + });
37
37 - Object.keys(results).sort().forEach(function(path){
38 - if (results[path].length > 0) {
38 + Object.keys(results).sort().forEach(function(concretePath) {
39 + if (results[concretePath].length > 0) {
40 return;
41 }
41 - var relativePath = path.replace(ROOT, '');
42 + var relativePath = concretePath.replace(ROOT, '');
43 grunt.log.ok('100% coverage ' + relativePath);
44 });
44 -
45 +
46 if (uncoveredExpressionCount > 0) {
47 grunt.log.error(uncoveredExpressionCount + ' expressions not covered');
48 }
grunt/tasks/download-previous-version.js
+30 -30
@@ -1,47 +1,47 @@
1 -"use strict";
1 +'use strict';
2
3 var grunt = require('grunt');
4 var http = require('http');
5 var fs = require('fs');
6 +var path = require('path');
7 +
8 +function get(url, targetFilePath, completedSuccessfully) {
9 + grunt.verbose.writeln('getting url \'' + url + '\'');
10 + http.get(url, function(response) {
11 + grunt.verbose.writeln('Received status code ' + response.statusCode + ' for \'' + url + '\'');
12 +
13 + if (response.statusCode !== 200) {
14 + if (response.headers.location) {
15 + get(response.headers.location, targetFilePath);
16 + return;
17 + } else {
18 + grunt.fatal('Nothing else to do.');
19 + completedSuccessfully(false);
20 + return;
21 + }
22 + }
23 + grunt.verbose.writeln('Writing url to \'' + targetFilePath + '\'');
24 + response.pipe(fs.createWriteStream(targetFilePath))
25 + .on('close', function() {
26 + completedSuccessfully(true);
27 + });
28 + });
29 +}
30
31 module.exports = function() {
32 var completedSuccessfully = this.async();
33 get(
10 - "http://react.zpao.com/builds/master/latest/react.min.js",
11 - __dirname + '/../../build/react-previous.min.js',
12 - function(success){
34 + 'http://react.zpao.com/builds/master/latest/react.min.js',
35 + path.join(__dirname, '/../../build/react-previous.min.js'),
36 + function(success) {
37 if (!success) {
38 return completedSuccessfully(success);
39 }
40 get(
17 - "http://react.zpao.com/builds/master/latest/JSXTransformer.js",
18 - __dirname + '/../../build/JSXTransformer-previous.js',
41 + 'http://react.zpao.com/builds/master/latest/JSXTransformer.js',
42 + path.join(__dirname, '/../../build/JSXTransformer-previous.js'),
43 completedSuccessfully
44 );
45 }
46 );
23 -
24 - function get(url, targetFilePath, completedSuccessfully) {
25 - grunt.verbose.writeln('getting url "' + url + '"');
26 - http.get(url, function(response) {
27 - grunt.verbose.writeln('Received status code ' + response.statusCode + ' for "' + url + '"');
28 -
29 - if (response.statusCode != 200) {
30 - if (response.headers.location) {
31 - get(response.headers.location, targetFilePath);
32 - return;
33 - } else {
34 - grunt.fatal('Nothing else to do.');
35 - completedSuccessfully(false);
36 - return;
37 - }
38 - }
39 - grunt.verbose.writeln('Writing url to "' + targetFilePath + '"');
40 - response.pipe(fs.createWriteStream(targetFilePath))
41 - .on('close', function() {
42 - completedSuccessfully(true);
43 - })
44 - ;
45 - });
46 - }
47 };
grunt/tasks/eslint.js new
+22
@@ -0,0 +1,22 @@
1 +'use strict';
2 +
3 +var grunt = require('grunt');
4 +
5 +module.exports = function() {
6 + var done = this.async();
7 + grunt.util.spawn({
8 + cmd: 'node_modules/.bin/eslint',
9 + args: ['src/', 'Gruntfile.js', 'grunt/', 'main.js', 'perf/', 'test/']
10 + }, function(err, result, code) {
11 + if (err) {
12 + grunt.log.error('Lint failed');
13 + } else {
14 + grunt.log.ok('Lint passed (but may contain warnings)');
15 + }
16 + if (result.stdout.length) {
17 + grunt.log.writeln(result.stdout);
18 + }
19 +
20 + done(code === 0);
21 + });
22 +};
grunt/tasks/gem-react-source.js
+14 -10
@@ -12,19 +12,21 @@ var buildFiles = [
12 ];
13
14 function buildRelease() {
15 - grunt.file.exists(dest) && grunt.file.delete(dest);
15 + if (grunt.file.exists(dest)) {
16 + grunt.file.delete(dest);
17 + }
18
19 // Copy gem-react-source/**/* to build/gem-react-source
20 var mappings = [].concat(
21 grunt.file.expandMapping('**/*', dest, {cwd: src})
22 );
23 mappings.forEach(function(mapping) {
22 - var src = mapping.src[0];
23 - var dest = mapping.dest;
24 - if (grunt.file.isDir(src)) {
25 - grunt.file.mkdir(dest);
24 + var mappingSrc = mapping.src[0];
25 + var mappingDest = mapping.dest;
26 + if (grunt.file.isDir(mappingSrc)) {
27 + grunt.file.mkdir(mappingDest);
28 } else {
27 - grunt.file.copy(src, dest);
29 + grunt.file.copy(mappingSrc, mappingDest);
30 }
31 });
32
@@ -36,7 +38,6 @@ function buildRelease() {
38 }
39
40 function packRelease() {
39 - /*jshint validthis:true */
41 var done = this.async();
42 var spawnCmd = {
43 cmd: 'gem',
@@ -46,12 +47,15 @@ function packRelease() {
47 }
48 };
49 grunt.util.spawn(spawnCmd, function(err, result) {
50 + if (err) {
51 + grunt.log.error(err);
52 + }
53 // Gem packing does weird things to versions so 0.12.0-alpha becomes
54 // 0.12.0.pre.alpha. We need to get the filename printed to stdout.
55 var filename = result.stdout.match(/File: (.*)$/)[1];
52 - var src = 'build/gem-react-source/' + filename;
53 - var dest = 'build/react-source.tgz';
54 - fs.rename(src, dest, done);
56 + var buildSrc = 'build/gem-react-source/' + filename;
57 + var buildDest = 'build/react-source.tgz';
58 + fs.rename(buildSrc, buildDest, done);
59 });
60 }
61
grunt/tasks/jsx.js
+11 -11
@@ -1,7 +1,7 @@
1 'use strict';
2
3 -var path = require("path");
4 -var grunt = require("grunt");
3 +var path = require('path');
4 +var grunt = require('grunt');
5 var expand = grunt.file.expand;
6 var spawn = grunt.util.spawn;
7
@@ -10,27 +10,27 @@ module.exports = function() {
10 var config = this.data;
11
12 var args = [
13 - "--cache-dir", ".module-cache",
14 - "--relativize",
15 - "--follow-requires",
16 - "--use-provides-module",
13 + '--cache-dir', '.module-cache',
14 + '--relativize',
15 + '--follow-requires',
16 + '--use-provides-module',
17 config.sourceDir,
18 config.outputDir
19 ];
20
21 var rootIDs = expand({
22 nonull: true, // Keep IDs that don't expand to anything.
23 - cwd: "src"
23 + cwd: 'src'
24 }, config.rootIDs).map(function(id) {
25 - return id.replace(/\.js$/i, "");
25 + return id.replace(/\.js$/i, '');
26 });
27
28 args.push.apply(args, rootIDs);
29 - args.push("--config" /* from stdin */);
29 + args.push('--config' /* from stdin */);
30
31 var child = spawn({
32 - cmd: "node",
33 - args: [path.join("bin", "jsx-internal")].concat(args)
32 + cmd: 'node',
33 + args: [path.join('bin', 'jsx-internal')].concat(args)
34 }, function(error, result, code) {
35 if (error) {
36 grunt.log.error(error);
grunt/tasks/npm-react-tools.js
+11 -10
@@ -7,7 +7,9 @@ var src = 'npm-react-tools';
7 var dest = 'build/npm-react-tools/';
8
9 function buildRelease() {
10 - grunt.file.exists(dest) && grunt.file.delete(dest);
10 + if (grunt.file.exists(dest)) {
11 + grunt.file.delete(dest);
12 + }
13
14 // read our required files from package.json
15 var pkgFiles = grunt.config.data.pkg.files;
@@ -27,18 +29,17 @@ function buildRelease() {
29 });
30
31 mappings.forEach(function(mapping) {
30 - var src = mapping.src[0];
31 - var dest = mapping.dest;
32 - if (grunt.file.isDir(src)) {
33 - grunt.file.mkdir(dest);
32 + var mappingSrc = mapping.src[0];
33 + var mappingDest = mapping.dest;
34 + if (grunt.file.isDir(mappingSrc)) {
35 + grunt.file.mkdir(mappingDest);
36 } else {
35 - grunt.file.copy(src, dest);
37 + grunt.file.copy(mappingSrc, mappingDest);
38 }
39 });
40 }
41
42 function packRelease() {
41 - /*jshint validthis:true */
43 var done = this.async();
44 var spawnCmd = {
45 cmd: 'npm',
@@ -48,9 +49,9 @@ function packRelease() {
49 }
50 };
51 grunt.util.spawn(spawnCmd, function() {
51 - var src = 'build/react-tools-' + grunt.config.data.pkg.version + '.tgz';
52 - var dest = 'build/react-tools.tgz';
53 - fs.rename(src, dest, done);
52 + var buildSrc = 'build/react-tools-' + grunt.config.data.pkg.version + '.tgz';
53 + var buildDest = 'build/react-tools.tgz';
54 + fs.rename(buildSrc, buildDest, done);
55 });
56 }
57
grunt/tasks/npm-react.js
+11 -10
@@ -15,7 +15,9 @@ var distFiles = [
15
16 function buildRelease() {
17 // delete build/react-core for fresh start
18 - grunt.file.exists(dest) && grunt.file.delete(dest);
18 + if (grunt.file.exists(dest)) {
19 + grunt.file.delete(dest);
20 + }
21
22 // mkdir -p build/react-core/lib
23 grunt.file.mkdir(lib);
@@ -27,12 +29,12 @@ function buildRelease() {
29 grunt.file.expandMapping('**/*', lib, {cwd: modSrc})
30 );
31 mappings.forEach(function(mapping) {
30 - var src = mapping.src[0];
31 - var dest = mapping.dest;
32 - if (grunt.file.isDir(src)) {
33 - grunt.file.mkdir(dest);
32 + var mappingSrc = mapping.src[0];
33 + var mappingDest = mapping.dest;
34 + if (grunt.file.isDir(mappingSrc)) {
35 + grunt.file.mkdir(mappingDest);
36 } else {
35 - grunt.file.copy(src, dest);
37 + grunt.file.copy(mappingSrc, mappingDest);
38 }
39 });
40
@@ -49,7 +51,6 @@ function buildRelease() {
51 }
52
53 function packRelease() {
52 - /*jshint validthis:true */
54 var done = this.async();
55 var spawnCmd = {
56 cmd: 'npm',
@@ -59,9 +60,9 @@ function packRelease() {
60 }
61 };
62 grunt.util.spawn(spawnCmd, function() {
62 - var src = 'build/react-' + grunt.config.data.pkg.version + '.tgz';
63 - var dest = 'build/react.tgz';
64 - fs.rename(src, dest, done);
63 + var buildSrc = 'build/react-' + grunt.config.data.pkg.version + '.tgz';
64 + var buildDest = 'build/react.tgz';
65 + fs.rename(buildSrc, buildDest, done);
66 });
67 }
68
grunt/tasks/npm.js
+24 -24
@@ -1,26 +1,26 @@
1 'use strict';
2
3 -var assert = require("assert");
4 -var path = require("path");
5 -var grunt = require("grunt");
3 +var assert = require('assert');
4 +var path = require('path');
5 +var grunt = require('grunt');
6 var spawn = grunt.util.spawn;
7
8 module.exports = function() {
9 var done = this.async();
10
11 function run(cmd, args, opts, callback) {
12 - assert.strictEqual(typeof cmd, "string");
12 + assert.strictEqual(typeof cmd, 'string');
13 assert.ok(args instanceof Array);
14
15 - if (typeof opts === "function" && !callback) {
15 + if (typeof opts === 'function' && !callback) {
16 callback = opts;
17 opts = {};
18 }
19
20 - assert.strictEqual(typeof opts, "object");
21 - assert.strictEqual(typeof callback, "function");
20 + assert.strictEqual(typeof opts, 'object');
21 + assert.strictEqual(typeof callback, 'function');
22
23 - grunt.log.writeln("> " + cmd + " " + args.join(" "));
23 + grunt.log.writeln('> ' + cmd + ' ' + args.join(' '));
24
25 // var proc =
26 spawn({
@@ -42,33 +42,33 @@ module.exports = function() {
42 }
43
44 var pkg = grunt.config.data.pkg;
45 - var tgz = pkg.name + "-" + pkg.version + ".tgz";
45 + var tgz = pkg.name + '-' + pkg.version + '.tgz';
46
47 - grunt.log.writeln("Packing " + tgz + " (this could take a while)...");
47 + grunt.log.writeln('Packing ' + tgz + ' (this could take a while)...');
48
49 - run("npm", ["pack", "--verbose", "."], function() {
50 - require("tmp").dir(function(err, dir) {
49 + run('npm', ['pack', '--verbose', '.'], function() {
50 + require('tmp').dir(function(err, dir) {
51 if (err) {
52 grunt.log.error(err);
53 done(false);
54 return;
55 }
56
57 - run("cp", [tgz, dir], function() {
58 - run("npm", [
59 - "install",
60 - "--production",
57 + run('cp', [tgz, dir], function() {
58 + run('npm', [
59 + 'install',
60 + '--production',
61 tgz
62 ], { cwd: dir }, function() {
63 - var nodePath = path.join(dir, "node_modules");
63 + var nodePath = path.join(dir, 'node_modules');
64 var pkgDir = path.join(nodePath, pkg.name);
65 var doneCount = 2;
66
67 // Make sure that bin/jsx is runnable by echoing main.js.
68 - run("bin/jsx", ["main.js"], {
68 + run('bin/jsx', ['main.js'], {
69 cwd: pkgDir
70 }, function(result) {
71 - assert.ok(result.stdout.indexOf("transform") >= 0, result.stdout);
71 + assert.ok(result.stdout.indexOf('transform') >= 0, result.stdout);
72
73 if (--doneCount === 0) {
74 done();
@@ -76,17 +76,17 @@ module.exports = function() {
76 });
77
78 // Make sure the .transform package method works.
79 - run("node", [
80 - "--print",
81 - 'require("react-tools").transform(' +
79 + run('node', [
80 + '--print',
81 + 'require(\'react-tools\').transform(' +
82 JSON.stringify(
83 - "/** @jsx React.DOM */ <div>oyez</div>;"
83 + '/** @jsx React.DOM */ <div>oyez</div>;'
84 ) + ')'
85 ], {
86 env: { NODE_PATH: nodePath }
87 }, function(result, code) {
88 assert.ok(result.stdout.indexOf(
89 - 'React.DOM.div(null, "oyez");'
89 + 'React.DOM.div(null, \'oyez\');'
90 ) >= 0, result.stdout);
91
92 if (--doneCount === 0) {
grunt/tasks/populist.js
+4 -3
@@ -2,12 +2,13 @@
2
3 var grunt = require('grunt');
4 var fs = require('fs');
5 +var path = require('path');
6
7 module.exports = function() {
8 var config = this.data;
9 var done = this.async();
10
10 - var theFilesToTestScript = fs.createWriteStream(__dirname + '/../../test/the-files-to-test.generated.js');
11 + var theFilesToTestScript = fs.createWriteStream(path.join(__dirname, '/../../test/the-files-to-test.generated.js'));
12 theFilesToTestScript.write('// Generated by ');
13 theFilesToTestScript.write(JSON.stringify(__filename.split(/(?=grunt)/)[1]));
14 theFilesToTestScript.write(' at ');
@@ -23,12 +24,12 @@ module.exports = function() {
24 nonull: true, // Keep IDs that don't expand to anything.
25 cwd: config.rootDirectory
26 }, requires).forEach(function(name) {
26 - name = name.replace(/\.js$/i, "");
27 + name = name.replace(/\.js$/i, '');
28 args.push(name);
29 theFilesToTestScript.write('harness.enableTest(' + JSON.stringify(name) + ');\n');
30 });
31
31 - require("populist").buildP({
32 + require('populist').buildP({
33 rootDirectory: config.rootDirectory,
34 args: args
35 }).then(function(output) {
grunt/tasks/release.js
+1 -5
@@ -1,6 +1,3 @@
1 -// function calls get bound so "possible strict mode violations" aren't
2 -// jshint -W040
3 -
1 'use strict';
2
3 var grunt = require('grunt');
@@ -59,8 +56,7 @@ function _gitCommitAndTag(cwd, commitMsg, tag, cb) {
56 grunt.util.spawn(gitCommit, function() {
57 if (tag) {
58 grunt.util.spawn(gitTag, cb);
62 - }
63 - else {
59 + } else {
60 cb();
61 }
62 });
grunt/tasks/sauce-tunnel.js
+2 -2
@@ -22,7 +22,7 @@ module.exports = function() {
22 var taskCompletedSuccessfully = task.async();
23
24 var stunnel = new SauceTunnel(SAUCE_USERNAME, SAUCE_ACCESS_KEY, IDENTIFIER, /*tunneled*/true, /*tunnelTimeout*/5);
25 - process.on('exit', stunnel.stop.bind(stunnel, function(){}));
25 + process.on('exit', stunnel.stop.bind(stunnel, function() {}));
26
27 stunnel.on('log:error', grunt.log.error.bind(grunt.log));
28 stunnel.on('log:writeln', grunt.log.writeln.bind(grunt.log));
@@ -32,7 +32,7 @@ module.exports = function() {
32 stunnel.on('verbose:debug', grunt.verbose.debug.bind(grunt.verbose));
33 stunnel.on('verbose:writeln', grunt.verbose.writeln.bind(grunt.verbose));
34
35 - stunnel.openTunnel(function(isOpen){
35 + stunnel.openTunnel(function(isOpen) {
36 if (shouldStayAliveForever && isOpen) {
37 grunt.verbose.writeln('Keeping the sauce-tunnel open forever because you used the keepalive flag `' + task.nameArgs + '`');
38 return;
grunt/tasks/webdriver-all.js
+15 -11
@@ -1,11 +1,10 @@
1 -/* jshint evil: true */
2 -
1 +/*eslint-disable consistent-return*/
2 'use strict';
3
5 -var grunt = require("grunt");
4 +var grunt = require('grunt');
5 var wd = require('wd');
6
8 -module.exports = function task(getJSReport){
7 +module.exports = function task(getJSReport) {
8 var config = this.data;
9 var taskSucceeded = this.async();
10 getJSReport = getJSReport.bind(this, config, wd);
@@ -19,7 +18,7 @@ module.exports = function task(getJSReport){
18 desiredCapabilities[key] = config.desiredCapabilities[key];
19 });
20 }
22 - grunt.verbose.writeln("desiredCapabilities", JSON.stringify(desiredCapabilities));
21 + grunt.verbose.writeln('desiredCapabilities', JSON.stringify(desiredCapabilities));
22
23 var browser = wd.promiseChainRemote(config.webdriver.remote);
24
@@ -38,18 +37,23 @@ module.exports = function task(getJSReport){
37 .init(desiredCapabilities)
38 .then(config.onStart && config.onStart.bind(config, browser))
39 .get(config.url)
41 - .then(function(){return browser;})
40 + .then(function() {
41 + return browser;
42 + })
43 .then(getJSReport)
43 - .then(function(data){ results = data; })
44 - .fail(function(error){
44 + .then(function(data) {
45 + results = data;
46 + })
47 + .fail(function(error) {
48 grunt.log.error(error);
49 return browser
50 .eval('document.documentElement.innerText || document.documentElement.textContent')
51 .then(grunt.verbose.writeln.bind(grunt.verbose))
49 - .then(function(){ throw error; })
50 - ;
52 + .then(function() {
53 + throw error;
54 + });
55 })
52 - .finally(function(){
56 + .finally(function() {
57 if (grunt.option('webdriver-keep-open')) {
58 return;
59 }
grunt/tasks/webdriver-jasmine.js
+8 -11
@@ -1,17 +1,14 @@
1 -/* jshint evil: true */
2 -
1 'use strict';
2
5 -module.exports = function(){
6 - return require('./webdriver-all').call(this, function(config, wd, browser){
3 +module.exports = function() {
4 + return require('./webdriver-all').call(this, function(config, wd, browser) {
5 return browser
8 - .waitFor(wd.asserters.jsCondition("typeof window.jasmine != 'undefined'"), 5e3, 50)
9 - .fail(function(error){
10 - throw Error("The test page didn't load properly. " + error);
6 + .waitFor(wd.asserters.jsCondition('typeof window.jasmine != \'undefined\''), 5e3, 50)
7 + .fail(function(error) {
8 + throw Error('The test page didn\'t load properly. ' + error);
9 })
12 - .waitFor(wd.asserters.jsCondition("typeof window.jasmine.getJSReport != 'undefined'"), 60e3, 100)
13 - .waitFor(wd.asserters.jsCondition("window.postDataToURL.running <= 0"), 30e3, 500)
14 - .eval("jasmine.getJSReport().passed")
15 - ;
10 + .waitFor(wd.asserters.jsCondition('typeof window.jasmine.getJSReport != \'undefined\''), 60e3, 100)
11 + .waitFor(wd.asserters.jsCondition('window.postDataToURL.running <= 0'), 30e3, 500)
12 + .eval('jasmine.getJSReport().passed');
13 });
14 };
grunt/tasks/webdriver-perf.js
+8 -11
@@ -1,23 +1,20 @@
1 -/* jshint evil: true */
2 -
1 'use strict';
2
3 var grunt = require('grunt');
4
7 -module.exports = function(){
8 - return require('./webdriver-all').call(this, function(config, wd, browser){
5 +module.exports = function() {
6 + return require('./webdriver-all').call(this, function(config, wd, browser) {
7 if (!config.isDoneTimeout) {
8 grunt.verbose.writeln('Expected isDoneTimeout config, using default value');
9 }
10 grunt.verbose.writeln('isDoneTimeout:' + config.isDoneTimeout);
11 return browser
14 - .waitFor(wd.asserters.jsCondition("window.isDone === false"), 5e3, 50)
15 - .fail(function(error){
16 - throw Error("The test page didn't load properly. " + error);
12 + .waitFor(wd.asserters.jsCondition('window.isDone === false'), 5e3, 50)
13 + .fail(function(error) {
14 + throw Error('The test page didn\'t load properly. ' + error);
15 })
18 - .waitFor(wd.asserters.jsCondition("window.isDone === true"), config.isDoneTimeout || 30e3, 1e3)
19 - .waitFor(wd.asserters.jsCondition("window.postDataToURL.running <= 0"), 30e3, 500)
20 - .eval("window.completedTestKeys || window._unhandledError")
21 - ;
16 + .waitFor(wd.asserters.jsCondition('window.isDone === true'), config.isDoneTimeout || 30e3, 1e3)
17 + .waitFor(wd.asserters.jsCondition('window.postDataToURL.running <= 0'), 30e3, 500)
18 + .eval('window.completedTestKeys || window._unhandledError');
19 });
20 };
grunt/tasks/webdriver-phantomjs.js
+6 -6
@@ -2,17 +2,17 @@
2
3 var grunt = require('grunt');
4
5 -module.exports = function(){
5 +module.exports = function() {
6 var onReadyCallback = this.async();
7
8 - var phantomjs = require("phantomjs").path;
9 - var child_process = require('child_process');
8 + var phantomjs = require('phantomjs').path;
9 + var childProcess = require('child_process');
10 var config = this.data || {};
11
12 - var args = ["--webdriver=" + (config.port || 9515)];
12 + var args = ['--webdriver=' + (config.port || 9515)];
13 grunt.verbose.writeln('phantomjs START path:%s args:%s', phantomjs, args);
14
15 - var child = child_process.spawn(phantomjs, args);
15 + var child = childProcess.spawn(phantomjs, args);
16 process.on('exit', function() {
17 child.kill();
18 });
@@ -29,7 +29,7 @@ module.exports = function(){
29 });
30
31 function verboseWrite(chunk) {
32 - if (onReadyCallback && chunk.toString().indexOf('running on port') != -1) {
32 + if (onReadyCallback && chunk.toString().indexOf('running on port') !== -1) {
33 grunt.verbose.writeln('phantomjs STARTED');
34 onReadyCallback();
35 onReadyCallback = null;
main.js
+1 -1
@@ -1,5 +1,5 @@
1 'use strict';
2 -
2 +/*eslint-disable no-undef*/
3 var visitors = require('./vendor/fbtransform/visitors');
4 var transform = require('jstransform').transform;
5 var typesSyntax = require('jstransform/visitors/type-syntax');
perf/.eslintrc new
+21
@@ -0,0 +1,21 @@
1 +globals:
2 + document: true
3 + window: true
4 + Benchmark: true
5 + React: true
6 + _rootNode: true
7 + todolist: true
8 + _app: true
9 + _todo1: true
10 + _todo2: true
11 + _todo3: true
12 + _timesToRun: true
13 + setState: true
14 +
15 +rules:
16 + strict: false
17 + no-undef: false
18 + no-unused-vars: false
19 + block-scoped-var: false
20 + consistent-return: false
21 + no-shadow: false
perf/lib/BrowserPerfRunnerApp.react.js
+60 -46
@@ -10,56 +10,59 @@ var BrowserPerfRunnerApp = React.createClass({
10 headless: React.PropTypes.bool
11 },
12
13 - getInitialState: function(){
13 + getInitialState: function() {
14 var queue = [];
15 - this.props.tests.forEach(function(testName){
16 - this.props.react.forEach(function(version){
15 + this.props.tests.forEach(function(testName) {
16 + this.props.react.forEach(function(version) {
17 queue.push({
18 test: testName,
19 react: version
20 });
21 - },this);
22 - },this);
21 + }, this);
22 + }, this);
23 return {
24 queue: queue,
25 results: {}
26 };
27 },
28
29 - handleResults: function(results){
29 + handleResults: function(results) {
30 this.state.results[results.test + '@' + results.react] = results;
31 this.replaceState(this.state);
32 },
33
34 - handleComplete: function(queueItem){
34 + handleComplete: function(queueItem) {
35 queueItem.completed = true;
36 -
36 +
37 if (!this.props.onCompleteEach) {
38 return;
39 }
40 // Can't get the resultsForAllVersions if there are still some queued
41 var incompleteCount = 0;
42 - for (var index = this.state.queue.length; --index >= 0;){
42 + for (var index = this.state.queue.length; --index >= 0;) {
43 if (this.state.queue[index].completed) {
44 continue;
45 }
46 if (this.state.queue[index].test === queueItem.test) {
47 return;
48 }
49 - incompleteCount ++;
49 + incompleteCount++;
50 }
51 var resultsForAllVersions = Object.keys(this.state.results)
52 - .filter(function(key){return key.indexOf(queueItem.test) === 0;})
53 - .map(function(key){return this.state.results[key];}, this)
54 - ;
52 + .filter(function(key) {
53 + return key.indexOf(queueItem.test) === 0;
54 + })
55 + .map(function(key) {
56 + return this.state.results[key];
57 + }, this);
58 this.props.onCompleteEach(resultsForAllVersions);
56 -
59 +
60 if (this.props.onComplete && incompleteCount === 0) {
61 this.props.onComplete(this.state.results);
62 }
63 },
64
62 - render: function(){
65 + render: function() {
66 var grid = null;
67
68 if (!this.props.headless) {
@@ -84,31 +87,38 @@ var BrowserPerfRunnerApp = React.createClass({
87 }
88 });
89
87 -BrowserPerfRunnerApp.renderBenchmarkCell = function(props, row, col){
88 - if (col == null && row == null) return React.DOM.th(null);
89 - if (row == null) return React.DOM.th({style:{verticalAlign:'top', textAlign:'center'}}, col);
90 +BrowserPerfRunnerApp.renderBenchmarkCell = function(props, row, col) {
91 + if (col == null && row == null) {
92 + return React.DOM.th(null);
93 + }
94 + if (row == null) {
95 + return React.DOM.th({style:{verticalAlign:'top', textAlign:'center'}}, col);
96 + }
97
98 var benchmarks = Object.keys(props.value)
92 - .filter(function(key){
99 + .filter(function(key) {
100 return key.indexOf(row) === 0;
101 })
95 - .map(function(key){
102 + .map(function(key) {
103 return props.value[key];
104 })
98 - .filter(function(benchmark){
105 + .filter(function(benchmark) {
106 return benchmark && !benchmark.isRunning && benchmark.stats;
100 - })
101 - ;
102 -
103 - if (col == null) return React.DOM.th({style:{verticalAlign:'top', textAlign:'right'}},
104 - React.DOM.a({href:'?test=' + row}, benchmarks[0] && benchmarks[0].name || row)
105 - );
107 + });
108 +
109 + if (col == null) {
110 + return React.DOM.th({style:{verticalAlign:'top', textAlign:'right'}},
111 + React.DOM.a({href:'?test=' + row}, benchmarks[0] && benchmarks[0].name || row)
112 + );
113 + }
114
115 var key = row + '@' + col;
116 var benchmark = props.value[key];
109 - if (!(benchmark && benchmark.stats)) return React.DOM.td({key:key});
110 -
111 -
117 + if (!(benchmark && benchmark.stats)) {
118 + return React.DOM.td({key:key});
119 + }
120 +
121 +
122 var colors = [
123 '000000',
124 'AA0000',
@@ -129,21 +139,25 @@ BrowserPerfRunnerApp.renderBenchmarkCell = function(props, row, col){
139 'FFFFFF'
140 ];
141
132 - function chartValue(value){
142 + function chartValue(value) {
143 return Math.round(valueFromRangeToRange(value, chartValue.min, chartValue.max, 0, 100));
144 }
135 - chartValue.min = Math.min.apply(Math, benchmarks.map(function(benchmark){return Math.min.apply(Math, benchmark.stats.sample);}));
136 - chartValue.max = Math.max.apply(Math, benchmarks.map(function(benchmark){return Math.max.apply(Math, benchmark.stats.sample);}));
137 -
138 - var means = benchmarks.map(function(benchmark){
145 + chartValue.min = Math.min.apply(Math, benchmarks.map(function(benchmark) {
146 + return Math.min.apply(Math, benchmark.stats.sample);
147 + }));
148 + chartValue.max = Math.max.apply(Math, benchmarks.map(function(benchmark) {
149 + return Math.max.apply(Math, benchmark.stats.sample);
150 + }));
151 +
152 + var means = benchmarks.map(function(benchmark) {
153 return benchmark.stats.mean;
154 });
141 - benchmarks.forEach(function(benchmark){
155 + benchmarks.forEach(function(benchmark) {
156 benchmark.isTheWinner = benchmark.stats.mean <= Math.min.apply(Math, means);
157 });
158
145 - var chartValues = benchmarks.map(function(benchmark){
146 - // benchmark.stats.sample.sort(function(a,b){return b - a;});
159 + var chartValues = benchmarks.map(function(benchmark) {
160 + // benchmark.stats.sample.sort(function(a,b) {return b - a;});
161 return benchmark.stats.sample.map(chartValue).join(',');
162 }).join('|');
163
@@ -151,9 +165,9 @@ BrowserPerfRunnerApp.renderBenchmarkCell = function(props, row, col){
165 React.DOM.td({key:key, style:{textAlign:'center', width:234, verticalAlign:'top'}},
166 benchmark.error && benchmark.error.message || '',
167 React.DOM.div({style: benchmark.isTheWinner ? { backgroundColor:'#0A5', color:'#AFA' } : {backgroundColor:'transparent', color:'inherit'}},
154 - Math.round(1 / benchmark.stats.mean * 100) / 100, " op/s ",
155 - React.DOM.strong(null, Math.round(benchmark.stats.mean * 1000 * 100) / 100, " ms/op "),
156 - React.DOM.small(null, "(±" + (Math.round(benchmark.stats.rme * 10) / 10) + "%)")
168 + Math.round(1 / benchmark.stats.mean * 100) / 100, ' op/s ',
169 + React.DOM.strong(null, Math.round(benchmark.stats.mean * 1000 * 100) / 100, ' ms/op '),
170 + React.DOM.small(null, '(±' + (Math.round(benchmark.stats.rme * 10) / 10) + '%)')
171 ),
172 benchmark.isRunning && 'Running' || React.DOM.img({
173 style: {
@@ -167,9 +181,9 @@ BrowserPerfRunnerApp.renderBenchmarkCell = function(props, row, col){
181 })
182 )
183 );
170 -}
184 +};
185
172 -function valueFromRangeToRange(value, fromMin, fromMax, toMin, toMax){
186 +function valueFromRangeToRange(value, fromMin, fromMax, toMin, toMax) {
187 var fromRange = fromMax - fromMin;
188 var toRange = toMax - toMin;
189 return (((value - fromMin) * toRange) / fromRange) + toMin;
@@ -183,11 +197,11 @@ var GridViewTable = React.createClass({
197 renderCell: React.PropTypes.func.isRequired
198 },
199
186 - _renderCell: function(col){
200 + _renderCell: function(col) {
201 return this.props.renderCell({ value:this.props.value }, this._row, col);
202 },
203
190 - _renderRow: function(row){
204 + _renderRow: function(row) {
205 this._row = row;
206 return React.DOM.tr({key:row},
207 this._renderCell(null, 0),
@@ -195,7 +209,7 @@ var GridViewTable = React.createClass({
209 );
210 },
211
198 - render: function(){
212 + render: function() {
213 return React.DOM.table(null,
214 this._renderRow(null, 0),
215 this.props.rows.map(this._renderRow, this)
perf/lib/BrowserPerfRunnerContext.react.js
+39 -33
@@ -8,25 +8,25 @@ var BenchmarkQueue = React.createClass({
8 onError: React.PropTypes.func
9 },
10
11 - getDefaultProps: function(){
11 + getDefaultProps: function() {
12 return {
13 maxTime: 5
14 };
15 },
16
17 - getInitialState: function(){
17 + getInitialState: function() {
18 return {
19 queue: this.props.initialQueue.slice()
20 };
21 },
22
23 - setItemState: function(state){
23 + setItemState: function(state) {
24 state.test = this.state.queue[0].test;
25 state.react = this.state.queue[0].react;
26 this.props.onChange(state);
27 },
28
29 - handleContextReady: function(window){
29 + handleContextReady: function(window) {
30 var benchmark = window.Benchmark(window.exports);
31 benchmark.options.maxTime = this.props.maxTime; //DEBUG
32
@@ -37,7 +37,7 @@ var BenchmarkQueue = React.createClass({
37 platform: window.Benchmark.platform.description,
38 reactVersion: window.React.version,
39
40 - isMinified: (function(){
40 + isMinified: (function() {
41 var code = window.React.render.toString();
42 return code.indexOf(',') - code.indexOf('(') <= 2;
43 }())
@@ -46,7 +46,7 @@ var BenchmarkQueue = React.createClass({
46 this.setItemState(itemState);
47
48 var self = this;
49 - benchmark.on('start error cycle complete', function(){
49 + benchmark.on('start error cycle complete', function() {
50 var stats = JSON.parse(JSON.stringify(benchmark.stats));
51 itemState.stats = stats;
52 itemState.isRunning = benchmark.running;
@@ -56,7 +56,7 @@ var BenchmarkQueue = React.createClass({
56 if (this.props.onError) {
57 benchmark.on('error', this.props.onError);
58 }
59 - benchmark.on('complete', function(){
59 + benchmark.on('complete', function() {
60 var queue = self.state.queue.slice();
61 var queueItem = queue.shift();
62 if (self.props.onCompleteEach) {
@@ -67,12 +67,12 @@ var BenchmarkQueue = React.createClass({
67 benchmark.run({async:true});
68 },
69
70 - shouldComponentUpdate: function(nextProps, nextState){
70 + shouldComponentUpdate: function(nextProps, nextState) {
71 return nextState.queue.length < this.state.queue.length;
72 },
73
74 - render: function(){
75 - if (!(this.state.queue && this.state.queue.length > 0)){
74 + render: function() {
75 + if (!(this.state.queue && this.state.queue.length > 0)) {
76 return React.DOM.div({style:{display:'none'}});
77 }
78 return BrowserPerfRunnerContext({
@@ -88,61 +88,67 @@ var BrowserPerfRunnerContext = React.createClass({
88
89 propTypes: {
90 debug: React.PropTypes.bool,
91 - test: function(object, key){
91 + test: function(object, key) {
92 React.PropTypes.string.isRequired(object, key);
93 - if (/\.jsx?$/i.test(object[key])) return;
93 + if (/\.jsx?$/i.test(object[key])) {
94 + return;
95 + }
96 throw Error('Expected `' + key + '` to be a test file name with extension `.js` or `.jsx`');
97 },
96 - react: function(object, key){
98 + react: function(object, key) {
99 React.PropTypes.string.isRequired(object, key);
98 - if (/^(?:builds\/.+|edge|previous|(?:\d+\.){2}\d+)$/.test(object[key])) return;
99 - throw Error('Expected `' + key + '` prop to be a valid react version string, build string or "edge" or "previous"');
100 + if (/^(?:builds\/.+|edge|previous|(?:\d+\.){2}\d+)$/.test(object[key])) {
101 + return;
102 + }
103 + throw Error('Expected `' + key + '` prop to be a valid react version string, build string or \'edge\' or \'previous\'');
104 },
105 onReady: React.PropTypes.func.isRequired
106 },
107
104 - getInitialState: function(){
108 + getInitialState: function() {
109 return {
110 testRunnerURL:'about:blank'
111 };
112 },
113
110 - // _handleFrameError: function(error){
114 + // _handleFrameError: function(error) {
115 // console.error('BrowserPerfRunnerContext', error);
116 // },
117 //
114 - // _handleFrameLoad: function(event){
118 + // _handleFrameLoad: function(event) {
119 // console.log('BrowserPerfRunnerContext', event);
120 // },
121 //
118 - _handleMessage: function(event){
119 - if (location.href.indexOf(event.origin) !== 0)
122 + _handleMessage: function(event) {
123 + if (location.href.indexOf(event.origin) !== 0) {
124 return console.debug('BrowserPerfRunnerContext#_handleMessage ignored message from ' + event.origin);
121 - if (event.source.location.href.indexOf(this.state.testRunnerURL) === -1)
125 + }
126 + if (event.source.location.href.indexOf(this.state.testRunnerURL) === -1) {
127 return console.debug('BrowserPerfRunnerContext#_handleMessage ignored message from ' + event.source.location.href);
123 - if (event.data !== 'Ready!')
128 + }
129 + if (event.data !== 'Ready!') {
130 return console.debug('BrowserPerfRunnerContext#_handleMessage ignored message ' + JSON.stringify(event.data));
125 -
131 + }
132 this.props.onReady(event.source);
133 },
134
129 - _getTestRunnerURL: function(props){
135 + _getTestRunnerURL: function(props) {
136 return 'runner.html' +
137 '?' +
138 'debug=' + (props.debug ? 1 : 0) +
139 '&' +
140 'react=' + encodeURIComponent(props.react) +
141 '&' +
136 - 'test=' + encodeURIComponent(props.test)
142 + 'test=' + encodeURIComponent(props.test);
143 },
144
139 - _renderState: function(props){
145 + _renderState: function(props) {
146 return {
147 testRunnerURL: this._getTestRunnerURL(props)
148 };
149 },
150
145 - componentDidMount: function(){
151 + componentDidMount: function() {
152 var node = this.refs.iframe.getDOMNode();
153 // node.onload = this._handleFrameLoad;
154 // node.onerror = this._handleFrameError;
@@ -156,7 +162,7 @@ var BrowserPerfRunnerContext = React.createClass({
162 this.setState(this._renderState(this.props));
163 },
164
159 - componentWillUnmount: function(){
165 + componentWillUnmount: function() {
166 if (window.removeEventListener) {
167 window.removeEventListener('message', this._handleMessage);
168 } else if (window.detachEvent) {
@@ -167,19 +173,19 @@ var BrowserPerfRunnerContext = React.createClass({
173 this.refs.iframe.getDOMNode().src = '';
174 },
175
170 - componentWillReceiveProps: function(nextProps){
176 + componentWillReceiveProps: function(nextProps) {
177 this.setState(this._renderState(nextProps));
178 },
179
174 - shouldComponentUpdate: function(nextProps, nextState){
175 - return nextState.testRunnerURL != this.state.testRunnerURL;
180 + shouldComponentUpdate: function(nextProps, nextState) {
181 + return nextState.testRunnerURL !== this.state.testRunnerURL;
182 },
183
178 - render: function(){
184 + render: function() {
185 return (
186 React.DOM.iframe({
187 ref: 'iframe',
182 - name: "BrowserPerfRunnerContextFrame",
188 + name: 'BrowserPerfRunnerContextFrame',
189 style: this.style,
190 src: this.state.testRunnerURL
191 })
perf/lib/perf-test-runner.browser.js
+101 -81
@@ -1,38 +1,44 @@
1 -if (typeof console == 'undefined') console = {
2 - log: function(){},
3 - warn: function(){},
4 - error: function(){},
5 - debug: function(){}
6 -};
1 +if (typeof console === 'undefined') {
2 + console = {
3 + log: function() {},
4 + warn: function() {},
5 + error: function() {},
6 + debug: function() {}
7 + };
8 +}
9
10 var perfRunner;
9 -if (typeof exports == 'object') {
11 +if (typeof exports === 'object') {
12 perfRunner = exports;
13 } else {
14 perfRunner = {};
15 }
16
15 -perfRunner.assert = function(test, message){
16 - if (typeof test == 'function') test = test();
17 - if (test) return;
17 +perfRunner.assert = function(test, message) {
18 + if (typeof test === 'function') {
19 + test = test();
20 + }
21 + if (test) {
22 + return;
23 + }
24 throw Error(message);
19 -}
25 +};
26
21 -perfRunner.WriteScript = function(props){
27 +perfRunner.WriteScript = function(props) {
28 var type = '';
29 if (props.jsx) {
24 - type = ' type="text/jsx"';
30 + type = ' type=\'text/jsx\'';
31 }
32 var src = props.src;
33 if (!props.cache) {
34 src += src.indexOf('?') === -1 ? '?_' : '&_';
35 src += perfRunner.WriteScript.cacheBust;
36 }
31 - document.write('<script' + type + ' src="' + src + '"><\/script>');
32 -}
33 -perfRunner.WriteScript.cacheBust = (+new Date).toString(36);
37 + document.write('<script' + type + ' src=\'' + src + '\'><\/script>');
38 +};
39 +perfRunner.WriteScript.cacheBust = (+new Date()).toString(36);
40
35 -perfRunner.WriteReactLibScript = function(params){
41 +perfRunner.WriteReactLibScript = function(params) {
42 var src;
43 var minSuffix;
44 if (params.debug) {
@@ -40,14 +46,16 @@ perfRunner.WriteReactLibScript = function(params){
46 } else {
47 minSuffix = '.min';
48 }
43 -
44 - if (params.version && typeof params.version != 'string') throw TypeError("Expected 'version' to be a string");
45 -
46 - if (params.version == 'edge' || !params.version) {
49 +
50 + if (params.version && typeof params.version !== 'string') {
51 + throw TypeError('Expected \'version\' to be a string');
52 + }
53 +
54 + if (params.version === 'edge' || !params.version) {
55 console.log('React edge (local)');
56 perfRunner.WriteScript({src:'../build/react' + minSuffix + '.js'});
57 perfRunner.WriteScript({src:'../build/JSXTransformer.js'});
50 - } else if (params.version == 'previous') {
58 + } else if (params.version === 'previous') {
59 console.log('React previous (local)');
60 perfRunner.WriteScript({cache:true, src:'../build/react-previous' + minSuffix + '.js'});
61 perfRunner.WriteScript({cache:true, src:'../build/JSXTransformer-previous.js'});
@@ -61,113 +69,123 @@ perfRunner.WriteReactLibScript = function(params){
69 }
70 if (params.debug) {
71 console.warn('Loading the unminified build of React, performance may suffer.');
64 - console.warn('Load "' + location.href.replace(/\bdebug=\w+&?|&\bdebug=\w+/ig, '') + '" for better perf.');
72 + console.warn('Load \'' + location.href.replace(/\bdebug=\w+&?|&\bdebug=\w+/ig, '') + '\' for better perf.');
73 } else {
74 console.warn('Loading the minified build of React, debugging may be harder.');
67 - console.warn('Load "' + location.href.replace(/\bdebug=\w+&?|&\bdebug=\w+/ig, '') + '&debug=1' + '" for easier debugging.');
75 + console.warn('Load \'' + location.href.replace(/\bdebug=\w+&?|&\bdebug=\w+/ig, '') + '&debug=1' + '\' for easier debugging.');
76 }
69 -}
77 +};
78
71 -perfRunner.WriteTestScript = function(params){
79 +perfRunner.WriteTestScript = function(params) {
80 if (Array.isArray(params.test)) {
81 return params.test
74 - .map(function(test){return {test:test};})
75 - .map(perfRunner.WriteTestScript)
76 - ;
82 + .map(function(test) {
83 + return {
84 + test:test
85 + };
86 + })
87 + .map(perfRunner.WriteTestScript);
88 }
89 perfRunner.assert(params.test.indexOf('..') === -1, 'no relative paths allowed');
90 return perfRunner.WriteScript({jsx:true, src: './tests/' + params.test});
80 -}
91 +};
92
82 -perfRunner.getQueryParamArray = function(key){
93 +perfRunner.getQueryParamArray = function(key) {
94 var values;
95 var queryString = location.search.substr(1);
96 var _key = encodeURIComponent(key) + '=';
86 -
97 +
98 if (queryString.indexOf(_key) > -1) {
99 values = queryString
100 .split(_key)
101 .slice(1)
91 - .map(function(part){return part.split('&')[0];})
102 + .map(function(part) {
103 + return part.split('&')[0];
104 + })
105 .map(decodeURIComponent)
93 - .map(function(string){
106 + .map(function(string) {
107 try {
108 return JSON.parse(string);
96 - } catch(e){}
109 + } catch(e) {}
110 return string;
98 - })
99 - ;
111 + });
112 }
101 -
113 +
114 perfRunner.assert(values && values.length && values[0], 'expected ' + key + ' query param');
115 return values;
104 -}
116 +};
117
106 -perfRunner.getQueryParamArrayOrDefault = function(key, defaultValue){
118 +perfRunner.getQueryParamArrayOrDefault = function(key, defaultValue) {
119 try {
120 return perfRunner.getQueryParamArray(key);
121 } catch (e) {}
122 return defaultValue;
111 -}
123 +};
124
113 -perfRunner.Polyfill = function(){
114 - if (typeof Function.prototype.bind != 'undefined') return;
125 +perfRunner.Polyfill = function() {
126 + if (typeof Function.prototype.bind !== 'undefined') {
127 + return;
128 + }
129 perfRunner.WriteScript({src:'/node_modules/es5-shim/es5-shim.js', cache:true});
130 perfRunner.WriteScript({src:'/node_modules/es5-shim/es5-sham.js', cache:true});
117 -}
131 +};
132
119 -perfRunner.BenchmarkResults = function(props){
120 - return perfRunner.roundNumberWithPrecision(props.stats.mean * 1000) + 'ms/op'
121 -}
133 +perfRunner.BenchmarkResults = function(props) {
134 + return perfRunner.roundNumberWithPrecision(props.stats.mean * 1000) + 'ms/op';
135 +};
136
123 -perfRunner.roundNumberWithPrecision = function(number, precision){
124 - if (!precision) precision = 1000;
137 +perfRunner.roundNumberWithPrecision = function(number, precision) {
138 + if (!precision) {
139 + precision = 1000;
140 + }
141 return Math.round(number * precision) / precision;
126 -}
142 +};
143
128 -perfRunner.quickBench = function(benchmarkOptions, onComplete, onBeforeStart){
144 +perfRunner.quickBench = function(benchmarkOptions, onComplete, onBeforeStart) {
145 var bench = new Benchmark(benchmarkOptions);
130 - if (onBeforeStart) onBeforeStart(null, bench);
146 + if (onBeforeStart) {
147 + onBeforeStart(null, bench);
148 + }
149
132 - bench.on('error', function(event){
150 + bench.on('error', function(event) {
151 console.error(event.message);
152 console.log(event.target.compiled.toString());
153 onComplete(Error(event.error));
154 });
155
138 - bench.on('start', function(){
156 + bench.on('start', function() {
157 console.log('starting', bench.name);
158 });
159
142 - bench.on('cycle', function(){
143 - var bench = this,
144 - size = bench.stats.size;
145 -
146 - if (!bench.aborted) {
147 - console.warn(bench.name + ' × ' + bench.count +
148 - ' (' + bench.stats.sample.length + ' samples)' +
149 - ' (' + Math.round(1 / bench.stats.mean) + ' ops/sec' + ')' +
150 - ' (' + (bench.stats.mean * 1000) + ' ms/op' + ')' +
151 - ' (±' + bench.stats.rme.toFixed(2) + '%)' +
160 + bench.on('cycle', function() {
161 + var benchmark = this,
162 + size = benchmark.stats.size;
163 +
164 + if (!benchmark.aborted) {
165 + console.warn(benchmark.name + ' × ' + benchmark.count +
166 + ' (' + benchmark.stats.sample.length + ' samples)' +
167 + ' (' + Math.round(1 / benchmark.stats.mean) + ' ops/sec' + ')' +
168 + ' (' + (benchmark.stats.mean * 1000) + ' ms/op' + ')' +
169 + ' (±' + benchmark.stats.rme.toFixed(2) + '%)' +
170 ' with ' + React.version
171 );
172 }
173 });
174
157 - bench.on('complete', function(){
175 + bench.on('complete', function() {
176 var results = {
177 platform: Benchmark.platform.description,
178 react: React.version,
161 - name: bench.name,
179 + name: bench.name
180 // times: bench.times,
181 // stats: bench.stats
182 };
165 -
166 - results['s/op'] = bench.stats.mean
167 - results['ms/op'] = results['s/op'] * 1000
168 - results['op/s'] = 1 / results['s/op']
169 - results["% frame 60"] = results['ms/op'] / (1000 / 60) * 100
170 -
183 +
184 + results['s/op'] = bench.stats.mean;
185 + results['ms/op'] = results['s/op'] * 1000;
186 + results['op/s'] = 1 / results['s/op'];
187 + results['% frame 60'] = results['ms/op'] / (1000 / 60) * 100;
188 +
189 console.log(results);
190 onComplete(null, results);
191 });
@@ -175,9 +193,9 @@ perfRunner.quickBench = function(benchmarkOptions, onComplete, onBeforeStart){
193 bench.run();
194 };
195
178 -perfRunner.singleTest = function(benchmarkOptions, onComplete){
196 +perfRunner.singleTest = function(benchmarkOptions, onComplete) {
197 var bench = Benchmark(exports);
180 - bench.on('complete', function(){
198 + bench.on('complete', function() {
199 var results = {
200 platform: Benchmark.platform.description,
201 react: React.version,
@@ -187,18 +205,20 @@ perfRunner.singleTest = function(benchmarkOptions, onComplete){
205 onComplete(results);
206 });
207 bench.run();
190 -}
208 +};
209
192 -perfRunner.ViewObject = function(props){
210 +perfRunner.ViewObject = function(props) {
211 var value = props.value;
212 delete props.value;
195 -
196 - if (typeof value != 'object') return React.DOM.span(props, [JSON.stringify(value), " ", typeof value]);
197 -
198 - return React.DOM.table(props, Object.keys(value).map(function(key){
213 +
214 + if (typeof value !== 'object') {
215 + return React.DOM.span(props, [JSON.stringify(value), ' ', typeof value]);
216 + }
217 +
218 + return React.DOM.table(props, Object.keys(value).map(function(key) {
219 return React.DOM.tr(null,
220 React.DOM.th(null, key),
221 React.DOM.td(null, perfRunner.ViewObject({key:key, value:value[key]}))
222 );
223 }));
204 -}
224 +};
perf/lib/todolist.browser.js
+56 -34
@@ -1,4 +1,4 @@
1 -/*global*/todolist = {};
1 +todolist = {};
2
3 todolist.ID = Date.now();
4
@@ -9,11 +9,15 @@ todolist.App = React.createClass({
9 fakeDataCount: React.PropTypes.number
10 },
11
12 - getInitialState: function(){
12 + getInitialState: function() {
13 var todos;
14 if (this.props.fakeDataCount) {
15 - todos = Array(this.props.fakeDataCount + 1).join(',').split(',').map(function(ignore, index){
16 - return {id:index, title:"Title " + index + " " + Math.random().toString(36).substring(2,16), completed:!!(index % 2)};
15 + todos = Array(this.props.fakeDataCount + 1).join(',').split(',').map(function(ignore, index) {
16 + return {
17 + id: index,
18 + title: 'Title ' + index + ' ' + Math.random().toString(36).substring(2, 16),
19 + completed: !!(index % 2)
20 + };
21 });
22 }
23 return {
@@ -23,15 +27,17 @@ todolist.App = React.createClass({
27 todos: todos || this.props.initialData || []
28 };
29 },
26 - componentWillUpdate: function(props, state){
27 - state.todos = state.todos.filter(function(todo){
30 + componentWillUpdate: function(props, state) {
31 + state.todos = state.todos.filter(function(todo) {
32 return !todo.deleted;
33 });
34 },
31 - addItem: function(title, callback){
35 + addItem: function(title, callback) {
36 if (title == null || title === '') {
37 var error = Error('invalid title');
34 - if (!callback) throw error;
38 + if (!callback) {
39 + throw error;
40 + }
41 return callback(error);
42 }
43 var todos = this.state.todos.slice();
@@ -41,82 +47,98 @@ todolist.App = React.createClass({
47 completed: false
48 };
49 todos.push(todo);
44 - if (callback) callback = callback.bind(this, todo);
50 + if (callback) {
51 + callback = callback.bind(this, todo);
52 + }
53 this.setState({ timerEvent:'addItem', timerStart:todolist.now(), timerEnd:null, todos:todos }, callback);
54 return todo;
55 },
48 - deleteItemById: function(id, callback){
56 + deleteItemById: function(id, callback) {
57 var todo = this._getById(id);
50 - if (!todo) return callback && callback(Error('todo with id ' + id + ' not found'));
58 + if (!todo) {
59 + return callback && callback(Error('todo with id ' + id + ' not found'));
60 + }
61 todo.deleted = true;
62 this.setState({ timerEvent:'deleteItemById', timerStart:todolist.now(), timerEnd:null, todos:this.state.todos }, callback);
63 },
54 - setItemCompleted: function(id, completed, callback){
64 + setItemCompleted: function(id, completed, callback) {
65 var todo = this._getById(id);
56 - if (!todo) return callback && callback(Error('todo with id ' + id + ' not found'));
66 + if (!todo) {
67 + return callback && callback(Error('todo with id ' + id + ' not found'));
68 + }
69 todo.completed = completed;
70 this.setState({ timerEvent:'setItemCompleted', timerStart:todolist.now(), timerEnd:null, todos:this.state.todos }, callback);
71 },
60 - _getById: function(id){
72 + _getById: function(id) {
73 id = +id;
74 var todos = this.state.todos;
63 - for (var index = todos.length; --index >= 0;){
64 - if (todos[index].id === id) return todos[index];
75 + for (var index = todos.length; --index >= 0;) {
76 + if (todos[index].id === id) {
77 + return todos[index];
78 + }
79 }
80 return null;
81 },
68 - _handleItemCompletedCheckboxChange: function(event){
82 + _handleItemCompletedCheckboxChange: function(event) {
83 var node = event.target;
84 this.setItemCompleted(node.value, node.checked);
85 },
72 - _handleItemDeletedButton: function(event){
86 + _handleItemDeletedButton: function(event) {
87 var node = event.target;
88 this.deleteItemById(node.value);
89 },
76 - _renderTodoItem: function(todo, index){
90 + _renderTodoItem: function(todo, index) {
91 return (
92 React.DOM.li({key:todo.id},
93 React.DOM.button({value:todo.id, onClick:this._handleItemDeletedButton}, 'x'),
80 - React.DOM.input({type:"checkbox", value:todo.id, checked:todo.completed, onChange:this._handleItemCompletedCheckboxChange}),
81 - " ",
82 - React.DOM.span({style:{"text-decoration":todo.completed ? "line-through" : ""}}, todo.title)
94 + React.DOM.input({type:'checkbox', value:todo.id, checked:todo.completed, onChange:this._handleItemCompletedCheckboxChange}),
95 + ' ',
96 + React.DOM.span({style:{'text-decoration':todo.completed ? 'line-through' : ''}}, todo.title)
97 )
98 );
99 },
86 - render: function(){
87 - if (!this.state.timerEnd) this.state.timerEnd = todolist.now();
88 - if (this.props.onRender) this.props.onRender();
100 + render: function() {
101 + if (!this.state.timerEnd) {
102 + this.state.timerEnd = todolist.now();
103 + }
104 + if (this.props.onRender) {
105 + this.props.onRender();
106 + }
107 return (
108 React.DOM.div(null,
91 - React.DOM.h1(null, "TODO"),
92 - React.DOM.h3(null, this.state.timerEvent, " ", this.state.timerEnd - this.state.timerStart, 'ms'),
109 + React.DOM.h1(null, 'TODO'),
110 + React.DOM.h3(null, this.state.timerEvent, ' ', this.state.timerEnd - this.state.timerStart, 'ms'),
111 todolist.NewItemForm({onEnter:this.addItem, autoFocus:true}),
112 React.DOM.ol(null, this.state.todos.map(this._renderTodoItem))
113 )
114 );
115 },
98 - componentDidMount: function(rootNode){
99 - if (this.props.onDidMount) this.props.onDidMount(rootNode);
116 + componentDidMount: function(rootNode) {
117 + if (this.props.onDidMount) {
118 + this.props.onDidMount(rootNode);
119 + }
120 }
121 });
122
123 todolist.NewItemForm = React.createClass({
104 - _handleNewItemKeyDown: function(event){
105 - if (event.which !== 13/*enter key*/) return;
124 + _handleNewItemKeyDown: function(event) {
125 + if (event.which !== 13/*enter key*/) {
126 + return;
127 + }
128 var node = this.refs.text.getDOMNode();
129 var value = node.value;
130 node.value = '';
131 this.props.onEnter(value);
132 return false;
133 },
112 - render: function(){
134 + render: function() {
135 var props = {};
136 for (var key in this.props) {
115 - if (key !== "onEnter") {
137 + if (key !== 'onEnter') {
138 props[key] = this.props[key];
139 }
140 }
119 - props.ref = "text";
141 + props.ref = 'text';
142 props.onKeyDown = this.props.onEnter && this._handleNewItemKeyDown;
143 return React.DOM.input(props);
144 }
perf/tests/basic-div.js
+4 -9
@@ -1,16 +1,11 @@
1 -/* jshint undef: true, unused: true */
2 -
3 -/* global document */
4 -/* global window */
5 -/* global Benchmark */
6 -/* global React */
7 -
8 -if (typeof exports == 'undefined') exports = {};
1 +if (typeof exports === 'undefined') {
2 + exports = {};
3 +}
4
5 /*http://benchmarkjs.com/docs#options*/
6
7 exports.name = 'React.DOM.div, no props';
8
14 -exports.fn = function(){
9 +exports.fn = function() {
10 React.DOM.div(null, 'lol, perf testing ', this.count);
11 };
perf/tests/basic-unmount.js
+11 -13
@@ -1,23 +1,21 @@
1 -/* jshint undef: true, unused: true */
2 -
3 -/* global document */
4 -/* global window */
5 -/* global Benchmark */
6 -/* global React */
7 -
8 -if (typeof exports == 'undefined') exports = {};
1 +if (typeof exports === 'undefined') {
2 + exports = {};
3 +}
4
5 /*http://benchmarkjs.com/docs#options*/
6
7 exports.name = 'unmountComponentAtNode';
8
14 -exports.setup = function(){
15 - /*global*/_rootNode = document.createElement('div');
9 +exports.setup = function() {
10 + _rootNode = document.createElement('div');
11 document.body.appendChild(_rootNode);
12 var _firstChild = React.DOM.div(null, 'lol, perf testing ', this.count);
13 React.render(_firstChild, _rootNode);
14 };
20 -exports.fn = function(){
21 - if (React.unmountAndReleaseReactRootNode) React.unmountAndReleaseReactRootNode(_rootNode);
22 - else React.unmountComponentAtNode(_rootNode);
15 +exports.fn = function() {
16 + if (React.unmountAndReleaseReactRootNode) {
17 + React.unmountAndReleaseReactRootNode(_rootNode);
18 + } else {
19 + React.unmountComponentAtNode(_rootNode);
20 + }
21 };
perf/tests/propTypes.js
+16 -10
@@ -1,4 +1,6 @@
1 -if (typeof exports == 'undefined') exports = {};
1 +if (typeof exports === 'undefined') {
2 + exports = {};
3 +}
4
5 /*http://benchmarkjs.com/docs#options*/
6
@@ -10,7 +12,11 @@ var ListItem;
12 var MyReactComponent;
13 var _rootNode;
14
13 -exports.setup = function(){
15 +function func() {
16 + return 'this is a function';
17 +}
18 +
19 +exports.setup = function() {
20 List = React.createClass({
21 propTypes: {
22 array: React.PropTypes.array,
@@ -38,7 +44,7 @@ exports.setup = function(){
44 instanceOf: React.PropTypes.instanceOf(Thing).isRequired,
45 element: React.PropTypes.element.isRequired
46 },
41 - render: function(){
47 + render: function() {
48 return React.DOM.li(null,
49 this.props.number + this.props.string + this.props.node
50 );
@@ -54,7 +60,7 @@ exports.setup = function(){
60 _rootNode = document.createElement('div');
61 document.body.appendChild(_rootNode);
62 };
57 -exports.fn = function(){
63 +exports.fn = function() {
64 var items = [];
65 for (var i = 0; i < 1000; i++) {
66 items.push(ListItem({
@@ -62,24 +68,24 @@ exports.fn = function(){
68 bool: false,
69 number: Math.random(),
70 string: 'banana banana banana',
65 - func: function() { return 'this is a function'; },
71 + func: func,
72 node: 'renderable string',
73 node2: [MyReactComponent(), 'a string'],
68 - instanceOf: new Thing,
74 + instanceOf: new Thing(),
75 element: MyReactComponent()
76 }));
71 - };
77 + }
78
79 React.render(List({
80 array: [11, 12, 13, 14, 15, 16, 17, 18, 19, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10],
81 bool: false,
82 number: Math.random(),
83 string: 'banana banana banana',
78 - func: function() { return 'this is a function'; },
84 + func: func,
85 renderable: 'renderable string',
80 - instanceOf: new Thing
86 + instanceOf: new Thing()
87 }, items), _rootNode);
88 };
83 -exports.teardown = function(){
89 +exports.teardown = function() {
90 React.unmountComponentAtNode(_rootNode);
91 };
perf/tests/renderComponent-basic.js
+12 -14
@@ -1,24 +1,22 @@
1 -/* jshint undef: true, unused: true */
2 -
3 -/* global document */
4 -/* global window */
5 -/* global Benchmark */
6 -/* global React */
7 -
8 -if (typeof exports == 'undefined') exports = {};
1 +if (typeof exports === 'undefined') {
2 + exports = {};
3 +}
4
5 /*http://benchmarkjs.com/docs#options*/
6
7 exports.name = 'React.render single div';
8
14 -exports.setup = function(){
15 - /*global*/_rootNode = document.createElement('div');
9 +exports.setup = function() {
10 + _rootNode = document.createElement('div');
11 document.body.appendChild(_rootNode);
12 };
18 -exports.fn = function(){
13 +exports.fn = function() {
14 React.render(React.DOM.div(null, 'lol, perf testing ', this.count), _rootNode);
15 };
21 -exports.teardown = function(){
22 - if (React.unmountAndReleaseReactRootNode) React.unmountAndReleaseReactRootNode(_rootNode);
23 - else React.unmountComponentAtNode(_rootNode);
16 +exports.teardown = function() {
17 + if (React.unmountAndReleaseReactRootNode) {
18 + React.unmountAndReleaseReactRootNode(_rootNode);
19 + } else {
20 + React.unmountComponentAtNode(_rootNode);
21 + }
22 };
perf/tests/sanity.js
+6 -4
@@ -1,15 +1,17 @@
1 -if (typeof exports == 'undefined') exports = {};
1 +if (typeof exports === 'undefined') {
2 + exports = {};
3 +}
4
5 /*http://benchmarkjs.com/docs#options*/
6
7 exports.name = 'Trivial benchmark to verify that everything works';
8
7 -exports.setup = function(){
9 +exports.setup = function() {
10 var foo;
11 };
10 -exports.fn = function(){
12 +exports.fn = function() {
13 foo = Array(999).join('Howdy!\n');
14 };
13 -exports.teardown = function(){
15 +exports.teardown = function() {
16 foo = null;
17 };
perf/tests/setState-callback-5.js
+18 -14
@@ -1,4 +1,6 @@
1 -if (typeof exports == 'undefined') exports = {};
1 +if (typeof exports === 'undefined') {
2 + exports = {};
3 +}
4
5 /*http://benchmarkjs.com/docs#options*/
6
@@ -6,29 +8,31 @@ exports.name = 'From setState to callback (x5)';
8
9 exports.defer = true;
10
9 -exports.setup = function(){
10 - /*global*/_rootNode = document.createElement('div');
11 +exports.setup = function() {
12 + _rootNode = document.createElement('div');
13 document.body.appendChild(_rootNode);
12 - /*global*/setState = null;
14 + setState = null;
15
16 var AwesomeComponent = React.createClass({
15 - getInitialState: function(){
17 + getInitialState: function() {
18 return { random:null };
19 },
18 - render: function(){
19 - if (!setState) setState = this.setState.bind(this);
20 + render: function() {
21 + if (!setState) {
22 + setState = this.setState.bind(this);
23 + }
24 return React.DOM.div(null, this.state.random);
25 }
26 });
27
28 React.render(AwesomeComponent(null), _rootNode);
29 };
26 -exports.fn = function(deferred){
27 - setState({random: Date.now() + Math.random()}, function(){
28 - setState({random: Date.now() + Math.random()}, function(){
29 - setState({random: Date.now() + Math.random()}, function(){
30 - setState({random: Date.now() + Math.random()}, function(){
31 - setState({random: Date.now() + Math.random()}, function(){
30 +exports.fn = function(deferred) {
31 + setState({random: Date.now() + Math.random()}, function() {
32 + setState({random: Date.now() + Math.random()}, function() {
33 + setState({random: Date.now() + Math.random()}, function() {
34 + setState({random: Date.now() + Math.random()}, function() {
35 + setState({random: Date.now() + Math.random()}, function() {
36 deferred.resolve();
37 });
38 });
@@ -36,6 +40,6 @@ exports.fn = function(deferred){
40 });
41 });
42 };
39 -exports.teardown = function(){
43 +exports.teardown = function() {
44 React.unmountComponentAtNode(_rootNode);
45 };
perf/tests/setState-callback.js
+14 -10
@@ -1,4 +1,6 @@
1 -if (typeof exports == 'undefined') exports = {};
1 +if (typeof exports === 'undefined') {
2 + exports = {};
3 +}
4
5 /*http://benchmarkjs.com/docs#options*/
6
@@ -6,28 +8,30 @@ exports.name = 'From setState to callback';
8
9 exports.defer = true;
10
9 -exports.setup = function(){
10 - /*global*/_rootNode = document.createElement('div');
11 +exports.setup = function() {
12 + _rootNode = document.createElement('div');
13 document.body.appendChild(_rootNode);
12 - /*global*/setState = null;
14 + setState = null;
15
16 var AwesomeComponent = React.createClass({
15 - getInitialState: function(){
17 + getInitialState: function() {
18 return { random:null };
19 },
18 - render: function(){
19 - if (!setState) setState = this.setState.bind(this);
20 + render: function() {
21 + if (!setState) {
22 + setState = this.setState.bind(this);
23 + }
24 return React.DOM.div(null, this.state.random);
25 }
26 });
27
28 React.render(AwesomeComponent(null), _rootNode);
29 };
26 -exports.fn = function(deferred){
27 - setState({random: Date.now() + Math.random()}, function(){
30 +exports.fn = function(deferred) {
31 + setState({random: Date.now() + Math.random()}, function() {
32 deferred.resolve();
33 });
34 };
31 -exports.teardown = function(){
35 +exports.teardown = function() {
36 React.unmountComponentAtNode(_rootNode);
37 };
perf/tests/shouldComponentUpdate.js
+8 -6
@@ -1,15 +1,17 @@
1 -if (typeof exports == 'undefined') exports = {};
1 +if (typeof exports === 'undefined') {
2 + exports = {};
3 +}
4
5 /*http://benchmarkjs.com/docs#options*/
6
7 exports.name = 'shouldComponentUpdate';
8
7 -exports.setup = function(){
9 +exports.setup = function() {
10 var AwesomeComponent = React.createClass({
9 - shouldComponentUpdate: function(){
11 + shouldComponentUpdate: function() {
12 return false;
13 },
12 - render: function(){
14 + render: function() {
15 return React.DOM.div({});
16 }
17 });
@@ -17,9 +19,9 @@ exports.setup = function(){
19 var _rootNode = document.createElement('div');
20 document.body.appendChild(_rootNode);
21 };
20 -exports.fn = function(){
22 +exports.fn = function() {
23 React.render(AwesomeComponent(null), _rootNode);
24 };
23 -exports.teardown = function(){
25 +exports.teardown = function() {
26 React.unmountComponentAtNode(_rootNode);
27 };
perf/tests/todolist-add.js
+12 -8
@@ -1,4 +1,6 @@
1 -if (typeof exports == 'undefined') exports = {};
1 +if (typeof exports === 'undefined') {
2 + exports = {};
3 +}
4
5 /*http://benchmarkjs.com/docs#options*/
6
@@ -6,20 +8,22 @@ exports.name = 'todolist from addItem to callback';
8
9 exports.defer = true;
10
9 -exports.setup = function(){
10 - /*global*/_rootNode = document.createElement('div');
11 +exports.setup = function() {
12 + _rootNode = document.createElement('div');
13 document.body.appendChild(_rootNode);
14 var appDescriptor = todolist.App({ fakeDataCount: 333 });
13 - /*global*/_app = React.render(appDescriptor, _rootNode);
15 + _app = React.render(appDescriptor, _rootNode);
16 };
15 -exports.fn = function(deferred){
17 +exports.fn = function(deferred) {
18 var liCount = document.getElementsByTagName('li').length;
17 - _app.addItem(Math.random(), function(){
18 - if (document.getElementsByTagName('li').length <= liCount) throw Error('expected a list item to be added to the dom');
19 + _app.addItem(Math.random(), function() {
20 + if (document.getElementsByTagName('li').length <= liCount) {
21 + throw Error('expected a list item to be added to the dom');
22 + }
23 deferred.resolve();
24 });
25 };
22 -exports.teardown = function(){
26 +exports.teardown = function() {
27 React.unmountComponentAtNode(_rootNode);
28 _rootNode.parentNode.removeChild(_rootNode);
29 _rootNode = null;
perf/tests/todolist-do-stuff.js
+19 -15
@@ -1,52 +1,56 @@
1 -if (typeof exports == 'undefined') exports = {};
1 +if (typeof exports === 'undefined') {
2 + exports = {};
3 +}
4
5 /*http://benchmarkjs.com/docs#options*/
6
5 -/*global*/_timesToRun = 2;
7 +_timesToRun = 2;
8
9 exports.name = 'todolist add, complete, remove (x' + _timesToRun + ')';
10
11 exports.defer = true;
12
11 -exports.setup = function(){
12 - /*global*/_rootNode = document.createElement('div');
13 +exports.setup = function() {
14 + _rootNode = document.createElement('div');
15 document.body.appendChild(_rootNode);
16 var appDescriptor = todolist.App({ fakeDataCount: 333 });
15 - /*global*/_app = React.render(appDescriptor, _rootNode);
17 + _app = React.render(appDescriptor, _rootNode);
18 };
19
18 -exports.fn = function(deferred){
20 +exports.fn = function(deferred) {
21 var originalLiCount = document.getElementsByTagName('li').length;
22
23 var todos = [];
24 var times = _timesToRun;
23 - while (times-- >= 0){
24 - todos.push(_app.addItem(times+1));
25 + while (times-- >= 0) {
26 + todos.push(_app.addItem(times + 1));
27 }
28
27 - todos.forEach(function(todo){
29 + todos.forEach(function(todo) {
30 _app.setItemCompleted(todo.id);
31 });
32
31 - todos.forEach(function(todo){
33 + todos.forEach(function(todo) {
34 _app.deleteItemById(todo.id);
35 });
36
37 todos = null;
38
37 - _app.addItem(Math.random(), function(todo){
38 - if (document.getElementsByTagName('li').length <= originalLiCount)
39 + _app.addItem(Math.random(), function(todo) {
40 + if (document.getElementsByTagName('li').length <= originalLiCount) {
41 throw Error('expected a list item to be added to the dom');
42 + }
43
41 - _app.deleteItemById(todo.id, function(){
42 - if (document.getElementsByTagName('li').length != originalLiCount)
44 + _app.deleteItemById(todo.id, function() {
45 + if (document.getElementsByTagName('li').length !== originalLiCount) {
46 throw Error('expected everything to be done by now');
47 + }
48 deferred.resolve();
49 });
50 });
51 };
52
49 -exports.teardown = function(){
53 +exports.teardown = function() {
54 React.unmountComponentAtNode(_rootNode);
55 _rootNode.parentNode.removeChild(_rootNode);
56 _rootNode = null;
perf/tests/todolist-edit.js
+12 -10
@@ -1,4 +1,6 @@
1 -if (typeof exports == 'undefined') exports = {};
1 +if (typeof exports === 'undefined') {
2 + exports = {};
3 +}
4
5 /*http://benchmarkjs.com/docs#options*/
6
@@ -6,25 +8,25 @@ exports.name = 'todolist setItemCompleted';
8
9 exports.defer = true;
10
9 -exports.setup = function(){
10 - /*global*/_rootNode = document.createElement('div');
11 +exports.setup = function() {
12 + _rootNode = document.createElement('div');
13 document.body.appendChild(_rootNode);
14 var appDescriptor = todolist.App({ fakeDataCount: 333 });
13 - /*global*/_app = React.render(appDescriptor, _rootNode);
14 - /*global*/_todo1 = _app.addItem("Howdy 1!");
15 - /*global*/_todo2 = _app.addItem("Howdy 2!");
16 - /*global*/_todo3 = _app.addItem("Howdy 3!");
15 + _app = React.render(appDescriptor, _rootNode);
16 + _todo1 = _app.addItem('Howdy 1!');
17 + _todo2 = _app.addItem('Howdy 2!');
18 + _todo3 = _app.addItem('Howdy 3!');
19 };
20
19 -exports.fn = function(deferred){
21 +exports.fn = function(deferred) {
22 _app.setItemCompleted(_todo1.id, !_todo1.completed);
23 _app.setItemCompleted(_todo2.id, !_todo2.completed);
22 - _app.setItemCompleted(_todo3.id, !_todo3.completed, function(){
24 + _app.setItemCompleted(_todo3.id, !_todo3.completed, function() {
25 deferred.resolve();
26 });
27 };
28
27 -exports.teardown = function(){
29 +exports.teardown = function() {
30 React.unmountComponentAtNode(_rootNode);
31 _rootNode.parentNode.removeChild(_rootNode);
32 _rootNode = null;
perf/tests/todolist-mount.js
+15 -8
@@ -1,22 +1,29 @@
1 -if (typeof exports == 'undefined') exports = {};
1 +if (typeof exports === 'undefined') {
2 + exports = {};
3 +}
4
5 /*http://benchmarkjs.com/docs#options*/
6
5 -exports.name = 'todolist from renderComponent to renderComponent callback (333 rows)';
7 +exports.name =
8 + 'todolist from renderComponent to renderComponent callback (333 rows)';
9
10 exports.defer = true;
11
9 -exports.setup = function(){
10 - if (typeof _rootNode != 'undefined') throw Error("should teardown before running setup again");
11 - /*global*/_rootNode = document.createElement('div');
12 +exports.setup = function() {
13 + if (typeof _rootNode !== 'undefined') {
14 + throw Error('should teardown before running setup again');
15 + }
16 + _rootNode = document.createElement('div');
17 document.body.appendChild(_rootNode);
18 };
19
15 -exports.fn = function(deferred){
16 - React.render(todolist.App({ fakeDataCount: 333 }), _rootNode, function(){ deferred.resolve(); });
20 +exports.fn = function(deferred) {
21 + React.render(todolist.App({ fakeDataCount: 333 }), _rootNode, function() {
22 + deferred.resolve();
23 + });
24 };
25
19 -exports.teardown = function(){
26 +exports.teardown = function() {
27 React.unmountComponentAtNode(_rootNode);
28 _rootNode.parentNode.removeChild(_rootNode);
29 _rootNode = undefined;
test/.eslintrc new
+8
@@ -0,0 +1,8 @@
1 +globals:
2 + harness: true
3 +
4 +rules:
5 + strict: false
6 + no-undef: false
7 + no-unused-vars: false
8 + block-scoped-var: false
\ No newline at end of file
test/lib/jasmine-execute.js
+5 -5
@@ -1,6 +1,6 @@
1 -document.write('<style> @import "../vendor/jasmine/jasmine.css?_=' + (+new Date).toString(36) + '"; </style>');
1 +document.write('<style> @import \'../vendor/jasmine/jasmine.css?_=' + (+new Date()).toString(36) + '\'; </style>');
2
3 -;(function(env){
3 +(function(env) {
4 var htmlReporter = new jasmine.HtmlReporter();
5 env.addReporter(htmlReporter);
6 env.specFilter = function(spec) {
@@ -10,10 +10,10 @@ document.write('<style> @import "../vendor/jasmine/jasmine.css?_=' + (+new Date)
10 // Clean up any nodes the previous test might have added.
11 env.afterEach(function() {
12 harness.removeNextSiblings(document.body);
13 - harness.removeNextSiblings(document.getElementById("HTMLReporter"));
13 + harness.removeNextSiblings(document.getElementById('HTMLReporter'));
14 });
15
16 - window.onload = function(){
16 + window.onload = function() {
17 env.execute();
18 - }
18 + };
19 })(jasmine.getEnv());
test/lib/postDataToURL.browser.js
+29 -15
@@ -1,34 +1,48 @@
1 -function createXMLHttpRequest(){
2 - try{return new XMLHttpRequest();}
3 - catch(e){}
4 - try {return new ActiveXObject("Msxml2.XMLHTTP");}
1 +/*eslint-disable brace-style*/
2 +function createXMLHttpRequest() {
3 + try {
4 + return new XMLHttpRequest();
5 + }
6 + catch(e) {}
7 + try {
8 + return new ActiveXObject('Msxml2.XMLHTTP');
9 + }
10 catch (e) {}
6 - try {return new ActiveXObject("Microsoft.XMLHTTP");}
11 + try {
12 + return new ActiveXObject('Microsoft.XMLHTTP');
13 + }
14 catch (e) {}
15 }
16 +/*eslint-enable brace-style*/
17
10 -function getURLSync(url){
18 +function getURLSync(url) {
19 var request = createXMLHttpRequest();
20 request.open('GET', url, /*asynchronous?*/false);
21 return request.responseText;
22 }
23
24 function postDataToURL(data, url, callback) {
17 - if (!callback) callback = postDataToURL.defaultCallback;
25 + if (!callback) {
26 + callback = postDataToURL.defaultCallback;
27 + }
28 var request = createXMLHttpRequest();
19 - if (!request) return callback(Error('XMLHttpRequest is unsupported'));
20 - postDataToURL.running = (postDataToURL.running||0) + 1;
21 - request.onreadystatechange = function(){
22 - if (request.readyState != 4) return;
29 + if (!request) {
30 + return callback(Error('XMLHttpRequest is unsupported'));
31 + }
32 + postDataToURL.running = (postDataToURL.running || 0) + 1;
33 + request.onreadystatechange = function() {
34 + if (request.readyState !== 4) {
35 + return;
36 + }
37 request.onreadystatechange = null;
24 - postDataToURL.running = (postDataToURL.running||0) - 1;
25 - callback(request.status == 200 ? null : request.status, request.responseText);
38 + postDataToURL.running = (postDataToURL.running || 0) - 1;
39 + callback(request.status === 200 ? null : request.status, request.responseText);
40 };
41 request.open('POST', url);
42 request.setRequestHeader('Content-Type', 'application/json');
43 request.send(JSON.stringify(data));
44 }
45
32 -postDataToURL.defaultCallback = function(error){
46 +postDataToURL.defaultCallback = function(error) {
47 // console.log('postDataToURL.defaultCallback', arguments)
34 -}
48 +};
test/lib/reportTestResults.browser.js
+31 -21
@@ -1,38 +1,46 @@
1 -var __DEBUG__ = location.search.substring(1).indexOf('debug') != -1;
1 +var __DEBUG__ = location.search.substring(1).indexOf('debug') !== -1;
2
3 -if (typeof console == 'undefined') console = {
4 - log: function(){},
5 - warn: function(){},
6 - error: function(){}
7 -};
3 +if (typeof console === 'undefined') {
4 + console = {
5 + log: function() {},
6 + warn: function() {},
7 + error: function() {}
8 + };
9 +}
10
11 var __consoleReport__ = [];
12
13 console._log = console.log;
12 -console.log = function(message){
14 +console.log = function(message) {
15 console._log(message);
14 - if (__DEBUG__) postDataToURL({type:'log', message:message}, '/reportTestResults');
15 - else __consoleReport__.push({type:'log', message:message});
16 -}
16 + if (__DEBUG__) {
17 + postDataToURL({type:'log', message:message}, '/reportTestResults');
18 + } else {
19 + __consoleReport__.push({type:'log', message:message});
20 + }
21 +};
22
23 console._error = console.error;
19 -console.error = function(message){
24 +console.error = function(message) {
25 console._error(message);
21 - if (__DEBUG__) postDataToURL({type:'error', message:message}, '/reportTestResults');
22 - else __consoleReport__.push({type:'error', message:message});
23 -}
26 + if (__DEBUG__) {
27 + postDataToURL({type:'error', message:message}, '/reportTestResults');
28 + } else {
29 + __consoleReport__.push({type:'error', message:message});
30 + }
31 +};
32
25 -console._flush = function(){
33 +console._flush = function() {
34 postDataToURL(__consoleReport__, '/console');
35 __consoleReport__.length = 0;
28 -}
36 +};
37
30 -;(function(env){
38 +(function(env) {
39 env.addReporter(new jasmine.JSReporter());
40 env.addReporter(new TAPReporter(console.log.bind(console)));
41
34 - function report(){
35 - if (typeof jasmine.getJSReport != 'function') {
42 + function report() {
43 + if (typeof jasmine.getJSReport !== 'function') {
44 return setTimeout(report, 100);
45 }
46 if (!__DEBUG__) {
@@ -42,8 +50,10 @@ console._flush = function(){
50 }
51
52 var oldCallback = env.currentRunner().finishCallback;
45 - env.currentRunner().finishCallback = function(){
46 - if (oldCallback) oldCallback.apply(this, arguments);
53 + env.currentRunner().finishCallback = function() {
54 + if (oldCallback) {
55 + oldCallback.apply(this, arguments);
56 + }
57 report();
58 };
59