Jest 15 has just been released and is way more awesome: http://facebook.github.io/jest/blog/2016/09/01/jest-15.html
This pull request updates jest from version 12 to 15. Right now there's a fix in jest around Symbol that hasn't been released yet, so this will break CI and cannot be merged it. But once it ships by the end of the day, we'll be good to go :)
See comments inline for all the changes I've done.
We currently write all our tests against the DOM implementation.
I need a way to run the Fiber tests against it. But I don't want
to take on any package dependencies on Fiber modules yet.
There's a problem with jest right now where you can't globally
mock modules that already exist. So I have to add a global call
to jest.mock.
Luckily we already have a way to test the useCreateElement paths
using a feature flag. I won't activate this flag in travis until
it passes, but the idea is to run all three variants in travis.
I'm not sure that invoking rAF and rIC synchronously is the best
way to test this since it doesn't capture the backwards
compatibility aspect. I.e. the fact that people might be relying
on the synchronous nature in real apps too. It's a start.
Ideally, jest would have these built-in.
Previously, the extract-components script would create the same number of layers of composites as the page it captures, but it would output a new class for each time any composite is used (since we don't want to replicate all the component logic).
I changed the script to output a single type for each type in the input -- and each generated component takes an index for which output it should return. This should be closer to how the original code behaves, especially with respect to VM function call lookups where the amount of polymorphism makes a difference.
I re-recorded the benchmarks with the new scripts. They run significantly faster:
```
Comparing old.txt (control) vs new.txt (test)
Significant differences marked by ***
% change from control to test, with 99% CIs:
* ssr_pe_cold_ms_jsc_jit
% change: -41.73% [-43.37%, -40.09%] ***
means: 39.3191 (control), 22.9127 (test)
* ssr_pe_cold_ms_jsc_nojit
% change: -44.24% [-46.69%, -41.80%] ***
means: 45.8646 (control), 25.5764 (test)
* ssr_pe_cold_ms_node
% change: -45.61% [-47.38%, -43.85%] ***
means: 90.1118 (control), 49.0116 (test)
```
This is probably in part due to the changes here, but also the page I captured has changed somewhat in the meantime and there seem to be slightly fewer components in the hierarchy, so they're not really comparable. But going forward we can use this benchmark which should be more accurate. I also included an identical copy that uses stateless functional components so we can test optimizations to those later.
Test Plan: Changed the preprocessor to log the output of babel.transform and saw
```
var _jsxFileName = 'src/isomorphic/modern/element/__tests__/ReactJSXElementValidator-test.js';
```
in the resulting output, instead of an absolute path.
Running this is left as an exercise for the reader, since my measure.py isn't designed for this at present. But something like this might work:
```diff
diff --git a/scripts/bench/measure.py b/scripts/bench/measure.py
index 4cedf47..627ec97 100755
--- a/scripts/bench/measure.py
+++ b/scripts/bench/measure.py
@@ -79,15 +79,12 @@ def _measure_ssr_ms(engine, react_path, bench_name, bench_path, measure_warm):
if (typeof React !== 'object') throw new Error('React not laoded');
report('factory_ms', END - START);
- globalEval(readFile(ENV.bench_path));
- if (typeof Benchmark !== 'function') {
- throw new Error('benchmark not loaded');
- }
+ globalEval("bm = (function(){" + readFile("bench-createclass-madman.js") + "})");
+ bm();
var START = now();
- var html = React.renderToString(React.createElement(Benchmark));
- html.charCodeAt(0); // flatten ropes
+ bm();
var END = now();
- report('ssr_' + ENV.bench_name + '_cold_ms', END - START);
+ report('cc_' + ENV.bench_name + '_cold_ms', END - START);
var warmup = ENV.measure_warm ? 80 : 0;
var trials = ENV.measure_warm ? 40 : 0;
@@ -119,7 +116,7 @@ def _main():
return 1
react_path = sys.argv[1]
- trials = 30
+ trials = 60
sys.stderr.write("Measuring SSR for PE benchmark (%d trials)\n" % trials)
for i in range(trials):
for engine in [
@@ -132,7 +129,7 @@ def _main():
sys.stderr.flush()
sys.stderr.write("\n")
- trials = 3
+ trials = 0#3
sys.stderr.write("Measuring SSR for PE with warm JIT (%d slow trials)\n" % trials)
for i in range(trials):
for engine in [
```
Works at least on a CentOS 7 machine after running `sudo yum install
webkitgtk webkitgtk-devel`.
The only globals you get are `print` and `PerfCounters`. No `console` nor the other globals provided by the `jsc` command-line tool (load, readFile, etc) though they're probably not hard to implement.
You can disable the JIT by setting the environment variable `JSC_useJIT=false`.
Test Plan:
```
~/local/react/scripts/perf-counters$ make
~/local/react/scripts/perf-counters$ build/jsc-perf <(echo 'PerfCounters.init(); var a = PerfCounters.getCounters().instructions; print("moo"); var b = PerfCounters.getCounters().instructions; print(b - a);')
moo
72182
~/local/react/scripts/perf-counters$
```
You could make the argument that this should be optional, but it doesn't
work without it so we might as well just enforce it.
Makes `jest` work by default.
Turns out jest is _incredibly_ slow at resolving require paths like `require('fbjs/lib/foo')`. Like several milliseconds per require. Really adds up when all our files require `invariant` and `warning`. Here's a temporary hack to make things fast again.
Test Plan:
```
npm test src/renderers/shared/reconciler/__tests__/ReactCompositeComponent-test.js
```
has a self-proclaimed runtime of ~8 seconds now instead of ~35 seconds.