Commit Graph

270 Commits

Author SHA1 Message Date
Dominic Gannaway
d94f231718 React option better stats
Summary:
Release notes: adds `reactOptimizeNestedFunctions` flag to enable nested optimized functions from React components

This PR adds output for components that fail to inline (during evaluation process) and adds a flag so we can enable/disable nested optimized functions in React components (from things like unknown array map functions).
Closes https://github.com/facebook/prepack/pull/2054

Differential Revision: D8202653

Pulled By: trueadm

fbshipit-source-id: 9ea95720e5296e602068ca4fe111ab303b8b24fc
2018-05-30 14:32:13 -07:00
Dominic Gannaway
fdc7ba549f Cleanup of all the React reconciler logic + remove mutations on ReactElements
Summary:
Release notes: none

This PR is a general spring cleaning of all the React logic. Nothing is fixed, but the logic for many of the aspects of the React reconciliation have been simplified and tidied up.

- I've removed all cases of mutating ReactElements, we now create new ReactElements instead of mutating – because, well, ReactElements are immutable (as are props).
- Removed ReactSerializerState and moved the logic that previous existed into `realm.react`.
- Simplified the branching logic of the reconciler so we no longer need to pass around state and instead use the existing conditional logic.

Manually tested on all our internal bundles are we have no failures.
Closes https://github.com/facebook/prepack/pull/2039

Reviewed By: gaearon

Differential Revision: D8205619

Pulled By: trueadm

fbshipit-source-id: a84c363038086b490d761dbe18711d617058f05c
2018-05-30 12:39:22 -07:00
Dominic Gannaway
bd29f451fd Tidy up simple tests and fix refuseSerialization bug
Summary:
Release note: none

This PR remove `firstRenderOnly` from a bunch of tests that shouldn't have had it and adds a new test for a big with `props` being incorrectly marked for `refuseSerialization` – `props` can be serialialized without the ReactElement, and the test shows how this might happen.
Closes https://github.com/facebook/prepack/pull/2057

Differential Revision: D8203483

Pulled By: gaearon

fbshipit-source-id: fbfb9cc3bbdadaba5884f87319cb5b54e4a0657a
2018-05-30 10:49:05 -07:00
Herman Venter
26290ddd00 Fix lint errors
Summary:
Release note: none

Fix lint errors that came our way via an internal check in.
Closes https://github.com/facebook/prepack/pull/2052

Differential Revision: D8197681

Pulled By: hermanventer

fbshipit-source-id: fdc481228239dcc1eeafc904536188e25289162a
2018-05-29 17:48:22 -07:00
Dan Abramov
5d45e5a7eb Fix test output
Summary: This ensures failing output for Prepack gets proxied into the actual logs in terminal and Sandcastle. That was the case for Jest, but not for Prepack itself. This surfaces the real error in D8188966, for example.

Reviewed By: sophiebits

Differential Revision: D8191668

fbshipit-source-id: d0e3e9ddc1f7b38157fc57a010026de9bb0ec79a
2018-05-29 14:39:17 -07:00
Dominic Gannaway
829acd5f64 Properly handle defaultProps with creation of ReactElements
Summary:
Release notes: none

After discussions last night with sebmarkbage, I noticed that we apply defaultProps in the wrong place when the config is partial object or an abstract object. This now uses a helper function, which is injected once for the entire bundle, that handles `defaultProps` cases as a temporal function entry. Added a regression test too.
Closes https://github.com/facebook/prepack/pull/2036

Differential Revision: D8175799

Pulled By: trueadm

fbshipit-source-id: b6bb4f30ee07f0bd9ac07fc91018c26936696f4b
2018-05-26 10:30:33 -07:00
Dominic Gannaway
47f84b405a Re-factor of the React createElement logic
Summary:
Release notes: none

Now that we have snapshotting from Object.assign and ToObject for abstracts, we can now upgrade the ReactElement creation logic, simplifying a bunch of routes which actually resulted in a bunch of components inlining in tests where they didn't before. Furthermore, it allows us to tighten up the Flow typings in the React reconciler and tidy up some of the checks for `key`s or `ref`s logic, which was a bit hard to read before and didn't take into account objects with multiple values in their values domain. This also fixes a bug with abstract conditional component types not getting the deafultProps values correctly.
Closes https://github.com/facebook/prepack/pull/1996

Differential Revision: D8172083

Pulled By: trueadm

fbshipit-source-id: 0a8a1e0631883c92e914aba1308a109b3afda137
2018-05-25 18:34:12 -07:00
Dominic Gannaway
3d35fc8cbd Fix react tests
Summary:
Release notes: none

An test only was accidentally merged to master.
Closes https://github.com/facebook/prepack/pull/2014

Differential Revision: D8134882

Pulled By: trueadm

fbshipit-source-id: 55194aa25aea409b6163c04f3d222f77c42acc6c
2018-05-24 02:55:31 -07:00
Dominic Gannaway
74ae4f86dd Add ReactDOM.createPortal inlining
Summary:
Release notes: adds support for ReactDOM.createPortal inlining

Allows the React reconciler to inline components passed to ReactDOM.createPortal.
Closes https://github.com/facebook/prepack/pull/2006

Differential Revision: D8125418

Pulled By: trueadm

fbshipit-source-id: a25a2c23d1dcaa2edaada6fecb39ef80bb829cff
2018-05-23 15:24:35 -07:00
Dominic Gannaway
87591341b1 Add __doNotRender flag to React reconcilation
Summary:
Release notes: opt out of optimizing a React component in a tree with `__doNotRender`

This PR makes it possible to opt out of a single component in a React component tree by detecting a `__doNotRender` flag. For example:

```js
function MyComponent(props) {
   ...
}

MyComponent.__doNotRender = true;

class MyComponent extends React.Component {
  render() {
    ...
  }
}

MyComponent.__doNotRender = true;
```
Closes https://github.com/facebook/prepack/pull/2004

Differential Revision: D8123009

Pulled By: trueadm

fbshipit-source-id: d5fc54aea2ea1253e260e41c1fb7d4f2d4717ffd
2018-05-23 11:53:46 -07:00
Dominic Gannaway
cde1af298d Do not mutate arrays or ReactElements during React reconciliation
Summary:
Release notes: none

This fixes an issue that we were experiencing, that turned out to be the correct fix after looking at https://github.com/facebook/prepack/pull/1997. We shouldn't mutate arrays in the reconciliation process, instead we should create new ones when we have new values. Also, we should ensure that we don't mutate ReactElements during reconciliation too, instead we should just create new ones. Mutating existing objects and values breaks down completely when we enter nested effects that need to re-evaluate the same original values, so this fixes a bunch of internal issues we were seeing on our internal FB bundle.
Closes https://github.com/facebook/prepack/pull/1999

Differential Revision: D8105499

Pulled By: trueadm

fbshipit-source-id: 4e6ceb8b02c886c42156a8903c347765f101c840
2018-05-22 16:35:40 -07:00
Dominic Gannaway
393eba15ad Ensures all serializer test case output passes linting validation
Summary:
Release notes: all serializer tests now get linted via ESlint for correct output

This PR is pretty gigantic, but almost 99% of it is changing all the serializer tests so they pass the linting rules – which means that there must be no undefined variables or if they are, they are explicitly accesses via `global`. Furthermore, the linting also checks to ensure that all variables are defined before they are used.

Also I added a regression test `conditions3` that further validates some complex cases I was seeing fail in other cases. The ESlint config is also in its own module so it can be shared between `debug-fb-www`.
Closes https://github.com/facebook/prepack/pull/1998

Differential Revision: D8099445

Pulled By: trueadm

fbshipit-source-id: 4a03c57beb51e394bc7b334728090b9fc515eca8
2018-05-22 15:41:31 -07:00
Dominic Gannaway
195f68209a Always emit globals safe for strict mode
Summary:
Release notes: all globals emitted reference the global identifier

This is a PR to replace https://github.com/facebook/prepack/pull/1894 that fixes #1890. I found a much simpler fix was to ensure we always treat emitted globals as safe for strict mode regardless. I had to change a test that went against this assumption, but we end up with code that better conforms to strict mode without large changes under the hood to Prepack.
Closes https://github.com/facebook/prepack/pull/1911

Differential Revision: D8095772

Pulled By: trueadm

fbshipit-source-id: d4ed65ba8d52cdb0c8f2171d3f3c02bdd265c32d
2018-05-22 09:37:11 -07:00
Herman Venter
c83d8a350b Update build command to explictly invoke yarn build
Summary:
Release note: none

yarn install used to also invoke the build step. This changed a while ago, but this script was not updated accordingly. Apparently no-one noticed until now.
Closes https://github.com/facebook/prepack/pull/1990

Differential Revision: D8081630

Pulled By: hermanventer

fbshipit-source-id: 87a1f6b340010d27a76da39bb5569ffcb3f7a5b8
2018-05-22 04:31:58 -07:00
Dominic Gannaway
3545cd8327 Render optimized react-dom/server renderToString ahead of time
Summary:
Release notes: adds experimental `react-dom/server` ahead-of-time rendering to string

This PR was part of a small 1-2 day hackathton to see the applicability of creating a server-side renderer based almost entirely to be a 1:1 of `ReactDOMServer` from `react-dom/server` package. This is by no means a full, complete server renderer but is the foundations for us to do further work on this path in the future. Currently, it consists of a single Jest test, to ensure the output of the Hacker News benchmark matches that of the current ReactDOMServer `renderToString` output.

The performance results look very promising (there are some `console.time` lines you can comment out in the test to see the performance for yourself). This implantation essentially compiles away `react` and `react-dom/server` and instead injects runtime helper functions that do things that cannot be statically determined ahead of time.

Lots of features are missing behind `invariant` TODOs. This was done intentionally.
Closes https://github.com/facebook/prepack/pull/1940

Differential Revision: D8075964

Pulled By: trueadm

fbshipit-source-id: 33b3c7ba26b41871ccd15ad8bde4ad257009fed6
2018-05-21 08:59:20 -07:00
Dominic Gannaway
e78c69c28a Skip check on elementTypes in CreateListFromArrayLike if parameter is default
Summary:
Release notes: none

When we create an array with `CreateListFromArrayLike`, if the `elementTypes` parameter is left undefined, then skip the check that might throw an invariant if the passed in value is abstract.
Closes https://github.com/facebook/prepack/pull/1986

Differential Revision: D8071410

Pulled By: trueadm

fbshipit-source-id: f5944ecfc928fb9efe9120153e102faec9d5e2b6
2018-05-20 13:59:03 -07:00
Dominic Gannaway
4dda80e5be Add no-use-before-define to debug-fb-www script
Summary:
Release notes: none

This adds the `no-use-before-define` rule to `debug-fb-www` script. `variables` and `functions` are set to false, which allows them to be skipped if defined in a parent scope or if the function is in the same scope (as it gets hoisted), see: https://github.com/eslint/eslint/pull/7948/files. With our current internal bundle and latest master, this brings about a new error that wasn't previously emitted: `'_$Fg' was used before it was defined. (5525:15)`.  Fixes https://github.com/facebook/prepack/issues/1982
Closes https://github.com/facebook/prepack/pull/1984

Differential Revision: D8055274

Pulled By: trueadm

fbshipit-source-id: 93a672dd22bce8cd798ebbb7ed90536a847f9ecb
2018-05-18 02:16:46 -07:00
Dominic Gannaway
b9d43d5e7d Move React side-effect logic in to the ThrowCompletion
Summary:
Release notes: none

This moves the side-effect detection logic for React component renders into the ThrowCompletion itself.
Closes https://github.com/facebook/prepack/pull/1977

Differential Revision: D8031923

Pulled By: trueadm

fbshipit-source-id: 189a2c7b729276193344a926db8f5a747460a8da
2018-05-16 14:08:52 -07:00
Dylan
9eefb43b42 Implement const/let pattern declarations (ES6 destructuring)
Summary:
This should resolve #415.

Relevant part of the spec here: https://www.ecma-international.org/ecma-262/6.0/#sec-let-and-const-declarations-runtime-semantics-evaluation

For `// 3. Let env be the running execution context’s LexicalEnvironment.`, I assumed that the `env` variable passed to the function already fulfills and it's not necessary to retrieve it here.

I've omitted the `ReturnIfAbrupt(Value)` steps from the spec, as this is also done for the rest of the implementation in this file.

test262 has one additional test pass as a result of this change, though somewhat surprisingly it's for `for`.
I've verified in the command line REPL that destructuring assignment works as expected in the basic case.
Closes https://github.com/facebook/prepack/pull/1967

Differential Revision: D8027013

Pulled By: NTillmann

fbshipit-source-id: 845527bcca55c845aca993fd2c97349efcbd5f59
2018-05-16 10:33:19 -07:00
Dominic Gannaway
00d8a1a820 Throw an error when side-effectful logic happens in a React component tree
Summary:
Release notes: the React reconciler now throw a FatalError upon encountering side-effects in a render

This PR revamps the current React system's restrictions for what you can and can't do during the React reconcilation phase. This is a pretty large update but provides much better boundaries between what is "safe" and not "safe", thus reducing the constraints.

1. A new error `ReconcilerRenderBailOut` is thrown if something occurs in the React reconciliation that causes the render to fail and it's a hard fail – no recovering and continuing.
2. If you mutate a binding/object outside the render phase, given the React component render phase is meant to be "pure", a `ReconcilerRenderBailOut` will be thrown.
3. If you `throw` during the React reconciliation phase, again a `ReconcilerRenderBailOut` will be thrown.

In the future, we should maybe loosen the constraints around all this and maybe allow `throw`, but right now it's causing too much friction. We should attempt to make React components render phase as pure as possible – as it results in much better optimizations by a compiler because we can assert far more without things tripping us up.

Another point, regarding (1), is that we should ideally be able to recover from the error thrown in Prepack. The reason we can't and is something that might be a very deep issue in Prepack, is that effects don't properly restore when we have nested PossiblyNormalCompletions at work. Bindings get mutated on records from changes made within `evaluateForEffects` but never get reset when in nested PossiblyNormalCompletion. If I remove all the things that can cause `PossiblyNormalCompletion`s then everything works fine and bindings do get restored. We can remove the constraint on (1) once we've found and fixed that issue.
Closes https://github.com/facebook/prepack/pull/1860

Differential Revision: D7950562

Pulled By: trueadm

fbshipit-source-id: 4657e68b084c7069622e88c9655823b5f1f9386f
2018-05-10 07:50:24 -07:00
Dominic Gannaway
32d9973c30 Adds react-dom/server mocks
Summary:
Release notes: adds ReactDOMServer mocks

This adds ReactDOMServer mocks plus a test.
Closes https://github.com/facebook/prepack/pull/1896

Differential Revision: D7908920

Pulled By: trueadm

fbshipit-source-id: 1889efc3a0a9ff6e4d8d5ec26de5196d528e7eb0
2018-05-08 06:43:22 -07:00
Dan Abramov
1f73895352 Enable a non-failing React test
Summary:
It's passing now.

I guess https://github.com/facebook/prepack/pull/1860 will turn it into an error but there's no reason for it to stay disabled.
Closes https://github.com/facebook/prepack/pull/1885

Reviewed By: trueadm

Differential Revision: D7908325

Pulled By: gaearon

fbshipit-source-id: 9e3b97a4634d279d42098fdaf6c73ea3dcbb730e
2018-05-08 03:53:56 -07:00
Nikolai Tillmann
118d31aa49 Remove simple closures.
Summary:
Release notes: Removing --simpleClosures option.

This feature was never fully implemented and remained buggy.
Instead of having two distinct modes, let's rather try to improve
pointwise what we perceive as inacceptible for the regular way of
why closures work in the serializer.
Closes https://github.com/facebook/prepack/pull/1876

Differential Revision: D7889689

Pulled By: NTillmann

fbshipit-source-id: 782a6754408a9b250d45691274902c6bb2ed6924
2018-05-05 16:24:14 -07:00
Dominic Gannaway
3005452448 Fixes issues with React reconcilers abstract conditional evaluator
Summary:
Release notes: none

This fixes https://github.com/facebook/prepack/issues/1866. The React reconciler previously had somewhat broken logic when dealing with conditional that may require effects being joined together for things such as if statements. This re-uses the logic in `IfStatement` to ensure we get it right. Furthermore, I found a bug in `fb20.js` that failed unless we made sure we throw a `FatalError` in `AbstractObjectValue` where both consequent and alternate values are not found – like done in other methods in `AbstractObjectValue` joining together a value in this scenario actually generated broken output.
Closes https://github.com/facebook/prepack/pull/1874

Differential Revision: D7887489

Pulled By: trueadm

fbshipit-source-id: 64595296e5090b55a1670ab989e6737d7febab55
2018-05-05 04:18:35 -07:00
Herman Venter
41817e5915 Do not apply joined generators in incorporateSavedCompletion
Summary:
Release note: Fixed code duplication bug

Issue: #1829

When joining up a saved possibly abrupt completion with the current completion (in Functions.incorporateSavedCompletion), the state must be updated with the effects of the normal part of the join. The normal part of the join does not include the joined generator, so that must be explicitly excluded when applying the effects.

The subtle reason for this is that the type of join point is only known to the caller of incorporateSavedCompletion and, depending on the type of join point, some parts of the joined completion may be excised from the join and put back into a saved completion. This means that only the caller knows exactly which parts of the abrupt completions should have their effects (and generators) reflected in the current state.
Closes https://github.com/facebook/prepack/pull/1834

Differential Revision: D7848979

Pulled By: hermanventer

fbshipit-source-id: 80e61692ea8f3b57930b5125178b560fa3d47af5
2018-05-02 13:30:25 -07:00
Dominic Gannaway
3d86c16d30 Support abstract temporal fall back in UpdateExpression
Summary:
Release notes: Adds pure scope support for abstract arguments with UpdateExpression

Whilst trying to get more things to inline with the React compiler, I ran into `UpdateExpression` again. Specifically, where throwing a FatalError won't help – as the expression is at the root/body of a function that has no fallback. So digging into it, when in pure scope, we can assume that there will be no effectual `toString` on the `AbstractValue` – so we can emit a temporal to the generator body and havoc the abstract value.

With this PR applied, we can do further inlining. Here's the Hacker News benchmark (test included):

```jsx
(function() {

const React = require('React');
const PropTypes = require('PropTypes');
// the JSX transform converts to React, so we need to add it back in
this['React'] = React;

if (!this.__evaluatePureFunction) {
  this.__evaluatePureFunction = function(f) {
    return f();
  };
}

module.exports = this.__evaluatePureFunction(() => {

  function timeAge(time) {
    const now = new Date(2042, 1, 1).getTime() / 1000;
    const minutes = (now - time) / 60;

    if (minutes < 60) {
      return Math.round(minutes) + ' minutes ago';
    }
    return Math.round(minutes / 60) + ' hours ago';
  }

  function getHostUrl(url) {
    return (url + '').replace('https://', '').replace('http://', '').split('/')[
      0
    ];
  }

  function Story({story, rank}) {
    return (
      <React.Fragment>
        <tr className="athing">
          <td
            style={{
              verticalAlign: 'top',
              textAlign: 'right',
            }}
            className="title">
            <span className="rank">{rank}.</span>
          </td>
          <td
            className="votelinks"
            style={{
              verticalAlign: 'top',
            }}>
            <center>
              <a href="#">
                <div className="votearrow" titl="upvote" />
              </a>
            </center>
          </td>
          <td className="title">
            <a href="#" className="storylink">{story.title}</a>
            {story.url
              ? <span className="sitebit comhead">
                  {' ('}<a href="#">{getHostUrl(story.url)}</a>)
                </span>
              : null}
          </td>
        </tr>
        <tr>
          <td colSpan="2" />
          <td className="subtext">
            <span className="score">{story.score + ' points'}</span>
            {' by '}
            <a href="#" className="hnuser">{story.by}</a>
            {' '}
            <span className="age">
              <a href="#">{timeAge(story.time)}</a>
            </span>
            {' | '}
            <a href="#">hide</a>
            {' | '}
            <a href="#">{story.descendants || 0 + ' comments'}</a>
          </td>
        </tr>
        <tr
          style={{
            height: 5,
          }}
          className="spacer"
        />
      </React.Fragment>
    );
  }

  Story.propTypes = {
    story: PropTypes.shape({
      title: PropTypes.string,
      url: PropTypes.string,
      score: PropTypes.number,
      descendants: PropTypes.number,
      by: PropTypes.string,
      time: PropTypes.number,
    }),
    rank: PropTypes.number,
  };

  function StoryList({stories}) {
    return (
      <tr>
        <td>
          <table cellPadding="0" cellSpacing="0" className="itemlist">
            <tbody>
              {
                // we use Array.from to tell the compiler that this
                // is definitely an array object
                Array.from(stories).map((story, i) => (
                  <Story story={story} rank={++i} key={story.id} />
                ))
              }
            </tbody>
          </table>
        </td>
      </tr>
    );
  }

  function HeaderBar(props) {
    return (
      <tr style={{backgroundColor: '#222'}}>
        <table
          style={{
            padding: 4,
          }}
          width="100%"
          cellSpacing="0"
          cellPadding="0">
          <tbody>
            <tr>
              <td style={{width: 18, paddingRight: 4}}>
                <a href="#">
                  <img
                    src="logo.png"
                    width="16"
                    height="16"
                    style={{
                      border: '1px solid #00d8ff',
                    }}
                  />
                </a>
              </td>
              <td style={{lineHeight: '12pt'}} height="10">
                <span className="pagetop">
                  <b className="hnname">{props.title}</b>
                  <a href="#">new</a>
                  {' | '}
                  <a href="#">comments</a>
                  {' | '}
                  <a href="#">show</a>
                  {' | '}
                  <a href="#">ask</a>
                  {' | '}
                  <a href="#">jobs</a>
                  {' | '}
                  <a href="#">submit</a>
                </span>
              </td>
            </tr>
          </tbody>
        </table>
      </tr>
    );
  }

  HeaderBar.defaultProps = {
    title: 'React HN Benchmark',
  };

  class AppBody extends React.Component {
    render() {
      return (
        <React.Fragment>
          <HeaderBar />
          <tr height="10" />
          <StoryList stories={this.props.stories} limit={this.props.storyLimit} />
        </React.Fragment>
      );
    }
  }

  AppBody.defaultProps = {
    storyLimit: 10,
  };

  function App({stories}) {
    return (
      <center>
        <table
          id="hnmain"
          border="0"
          cellPadding="0"
          cellSpacing="0"
          width="85%"
          style={{
            backgroundColor: '#f6f6ef',
          }}>
          <tbody>
            {stories.length > 0 ? <AppBody stories={stories} /> : null}
          </tbody>
        </table>
      </center>
    );
  }

  App.getTrials = function(renderer, Root, data) {
    let results = [];
    renderer.update(<Root stories={data} />);
    results.push(['clone element (true)', renderer.toJSON()]);

    return results;
  };

  App.propTypes = {
    stories: PropTypes.array.isRequired,
  };

  if (this.__optimizeReactComponentTree) {
  	__optimizeReactComponentTree(App);
  }

  return App;
});

})();
```

Here is after using `createElement` output and with Google Closure Compiler then Prettier run on the output. As you can see, it's inlined all the components into a single functional component and hoisted out a large amount of completely static ReactElement nodes.

```jsx
(function() {
  var Q = require("React"),
    m = this.Object.assign,
    R = this.Array.from,
    S = require("React").createElement,
    f = function(p, f) {
      var b = p.stories,
        e = 0 < m(b).length;
      b = R(b).map(function(p, b) {
        var e = ++b,
          d = m(p),
          n = d.title,
          l = d.url;
        if (l) {
          var c = (d.url + "").replace("https://", "");
          m(c);
          c = c.replace("http://", "");
          m(c);
          c = c.split("/");
          var g = m(c)["0"];
        }
        var f = d.score + " points",
          k = d.by;
        c = 2274825600 - d.time;
        d = d.descendants;
        e = a("span", { className: "rank" }, e, ".");
        e = a(
          "td",
          {
            style: { verticalAlign: "top", textAlign: "right" },
            className: "title"
          },
          e
        );
        if (void 0 === q) {
          var h = a;
          q = h("div", { className: "votearrow", titl: "upvote" });
          u = h("a", { href: "#" }, q);
          v = h("center", null, u);
          w = h(
            "td",
            { className: "votelinks", style: { verticalAlign: "top" } },
            v
          );
          x = h("td", { colSpan: "2" });
          y = h("a", { href: "#" }, "hide");
          z = h("tr", { style: { height: 5 }, className: "spacer" });
        }
        n = a("a", { href: "#", className: "storylink" }, n);
        g = a("a", { href: "#" }, g);
        g = a("span", { className: "sitebit comhead" }, " (", g, ")");
        l = a("td", { className: "title" }, n, l ? g : null);
        l = a("tr", { className: "athing" }, e, w, l);
        f = a("span", { className: "score" }, f);
        k = a("a", { href: "#", className: "hnuser" }, k);
        c /= 60;
        n = Math.round(c);
        g = Math.round(c / 60);
        c = a(
          "a",
          { href: "#" },
          60 > c ? n + " minutes ago" : g + " hours ago"
        );
        c = a("span", { className: "age" }, c);
        d = a("a", { href: "#" }, d || "0 comments");
        d = a(
          "td",
          { className: "subtext" },
          f,
          " by ",
          k,
          " ",
          c,
          " | ",
          y,
          " | ",
          d
        );
        d = a("tr", null, x, d);
        return a(r.Fragment, null, l, d, z);
      });
      void 0 === k && T(a);
      b = a("tbody", null, b);
      b = a(
        "table",
        { cellPadding: "0", cellSpacing: "0", className: "itemlist" },
        b
      );
      b = a("td", null, b);
      b = a("tr", null, b);
      b = a(r.Fragment, null, A, B, b);
      e = a("tbody", null, e ? b : null);
      e = a(
        "table",
        {
          id: "hnmain",
          border: "0",
          cellPadding: "0",
          cellSpacing: "0",
          width: "85%",
          style: { backgroundColor: "#f6f6ef" }
        },
        e
      );
      return a("center", null, e);
    },
    t = function() {},
    r = Q;
  React = r;
  f.getTrials = _2J;
  t.isRequired = t;
  f.propTypes = { stories: t };
  var a = S,
    q,
    u,
    v,
    w,
    x,
    y,
    z,
    T = function(a) {
      k = a("img", {
        src: "logo.png",
        width: "16",
        height: "16",
        style: { border: "1px solid #00d8ff" }
      });
      C = a("a", { href: "#" }, k);
      D = a("td", { style: { width: 18, paddingRight: 4 } }, C);
      E = a("b", { className: "hnname" }, "React HN Benchmark");
      F = a("a", { href: "#" }, "new");
      G = a("a", { href: "#" }, "comments");
      H = a("a", { href: "#" }, "show");
      I = a("a", { href: "#" }, "ask");
      J = a("a", { href: "#" }, "jobs");
      K = a("a", { href: "#" }, "submit");
      L = a(
        "span",
        { className: "pagetop" },
        E,
        F,
        " | ",
        G,
        " | ",
        H,
        " | ",
        I,
        " | ",
        J,
        " | ",
        K
      );
      M = a("td", { style: { lineHeight: "12pt" }, height: "10" }, L);
      N = a("tr", null, D, M);
      O = a("tbody", null, N);
      P = a(
        "table",
        {
          style: { padding: 4 },
          width: "100%",
          cellSpacing: "0",
          cellPadding: "0"
        },
        O
      );
      A = a("tr", { style: { backgroundColor: "#222" } }, P);
      B = a("tr", { height: "10" });
    },
    k,
    C,
    D,
    E,
    F,
    G,
    H,
    I,
    J,
    K,
    L,
    M,
    N,
    O,
    P,
    A,
    B;
  module.exports = f;
}.call(this));
```
Closes https://github.com/facebook/prepack/pull/1839

Differential Revision: D7846721

Pulled By: trueadm

fbshipit-source-id: 761aab09721d05050ea8e71721cebb5ecdf371ee
2018-05-02 12:07:32 -07:00
Nikolai Tillmann
005bc1fa90 Aligning serializer with visitor for modified object properties
Summary:
Release notes: None

This fixes #1820.

Adding regression test.
Closes https://github.com/facebook/prepack/pull/1825

Differential Revision: D7845744

Pulled By: NTillmann

fbshipit-source-id: bd45ea0ae814fc585f1f3e1cb9013d8215021e80
2018-05-02 10:53:59 -07:00
Dominic Gannaway
057e48c96a Tidies up the React mock logic + ReactDOM mocks + few tweaks
Summary:
Release notes: adds ReactDOM mocks to fb-www compatibility mode

This PR aims to do a bunch of things:
- Tidy up the spaghetti React mock logic by adding in some helper functions
- Add ReactDOM mocks, pathing the way for greater optimizations for first render
- Swap the `Get` to a `getProperty` in `isReactElement` function
- Make the fb-www mocks not ignored by eslint and fix the eslint issues after doing so
Closes https://github.com/facebook/prepack/pull/1835

Differential Revision: D7845112

Pulled By: trueadm

fbshipit-source-id: 7173c543da6af2c20a38fbc70f962825647f8f3e
2018-05-02 09:08:00 -07:00
Dominic Gannaway
4fcc238259 Ensure we visit ReactLibrary with React.Fragment usage
Summary:
Release notes: none

This PR ensures we visit the React library when `React.Fragment` is used in a ReactElement. Fixes https://github.com/facebook/prepack/issues/1831.
Closes https://github.com/facebook/prepack/pull/1836

Differential Revision: D7844218

Pulled By: trueadm

fbshipit-source-id: 58d9391ee8ef8acc1363c74b66de8ad5f792657e
2018-05-02 07:41:45 -07:00
Dominic Gannaway
ee1b47625a Extend invariant check in AbstractObjectValue
Summary:
Release notes: none

This PR fixes https://github.com/facebook/prepack/issues/1819. It expands on the existing invariant check in `AbstractObjectValue` by also allowing abstract object values to pass through.
Closes https://github.com/facebook/prepack/pull/1824

Differential Revision: D7829938

Pulled By: trueadm

fbshipit-source-id: 7e198bc626b4fd2737d0ef9d2a7207bd17b0b02a
2018-05-01 09:19:01 -07:00
Herman Venter
7b66b43864 Enable fb-www 12
Summary:
Release note: none

Enable test fb-www 12.

While I'm at it, also update package.json to get rid of deprecated -- option and thus shut up a warning about it in CircleCI.
Closes https://github.com/facebook/prepack/pull/1817

Differential Revision: D7824465

Pulled By: hermanventer

fbshipit-source-id: ed88bd1ed8b02c560faf58be24a6592b3e55b86b
2018-04-30 18:25:44 -07:00
Herman Venter
7155b57790 Enable test fb-www 19
Summary:
Release note: none

Enable a test that is now working because of PR #1813.
Closes https://github.com/facebook/prepack/pull/1814

Differential Revision: D7823202

Pulled By: hermanventer

fbshipit-source-id: fb4bf726ffac55094851baf6eb19527671e12ad9
2018-04-30 17:24:02 -07:00
Dominic Gannaway
4302d24e51 Add a evaluateForEffectsWithPriorEffects to Realm
Summary:
Release notes: none

This should fix https://github.com/facebook/prepack/issues/1803 and extends from the unsuccessful attempts made in https://github.com/facebook/prepack/pull/1809 to fix this.

When we apply the `priorEffects` inside of the `evaluateForEffects` on TryStatement, we have to ensure that the `canBeApplied` flag is reset (as the bindings on the Realm get restored by `evaluateForEffects`).
Closes https://github.com/facebook/prepack/pull/1811

Differential Revision: D7820907

Pulled By: trueadm

fbshipit-source-id: 248cc0f21be0044de8641e79c5985c7259a88629
2018-04-30 15:40:16 -07:00
Dominic Gannaway
0c45892f45 isReactElement should check for type and props on the obj
Summary:
Release notes: none

This adds more validation that something definitely is a ReactElement, as found from the issue https://github.com/facebook/prepack/issues/1802. Unfortunately, the test in that case does not pass, it fails due to an invariant:

`Invariant Violation: an abstract value with an identifier "_$1" was referenced before being declared`
Closes https://github.com/facebook/prepack/pull/1810

Differential Revision: D7813932

Pulled By: trueadm

fbshipit-source-id: e431887002da83389da4062cfe00afbdc42d21c8
2018-04-30 10:49:37 -07:00
Dominic Gannaway
0f60e8c220 Write conflicts possibly normal completions
Summary:
Release notes: none

When digging deeper into detecting write conflicts with React component trees, I found that PossiblyNormalCompletions were not handled properly, so this PR ensures that the effects tree is recursively traversed so all modified bindings are collected, even from PossiblyNormalCompletions.

Update:
With all the latest changes, all tests in this PR now pass, so it's ready to be reviewed again.
Closes https://github.com/facebook/prepack/pull/1742

Differential Revision: D7813778

Pulled By: trueadm

fbshipit-source-id: 425ec505709c83081c7eef3bec9bf95bd651299e
2018-04-30 08:20:39 -07:00
Dominic Gannaway
fb6d352f46 Fixes an issue in the React reconciler when dealing with abstract values
Summary:
Release notes: none

This PR fixes an issue where the React reconciler incorrectly assumed that `createFromConditionalOp` always returned an `AbstractValue`. This changes that and adds the failing test for a regression test.

Fixes https://github.com/facebook/prepack/issues/1804.
Closes https://github.com/facebook/prepack/pull/1807

Differential Revision: D7813026

Pulled By: trueadm

fbshipit-source-id: 5af963fb0e2351d073df554cda33b979d52c9e60
2018-04-30 06:09:09 -07:00
Nikolai Tillmann
3fb0ee1a7b Ensure that the right effects are applied when visiting bindings.
Summary:
Release notes: None

This fixes #1798, and it almost fixes #1797 by reducing it to #1799, and it unblocks #1794.

When the visitor looks at (initial) function bindings, it does so with additional functions still applied if that additional function happens to be the first thing that pull on the function value.
This is being fixed, as well as generally turning _withScope uses into _enqueueWithUnrelatedScope calls which ensure that the right effects are in place.

Added additional output to the serializer runner - it now shows a summary of which tests failed, ordered by their size.

Added regression test.
Closes https://github.com/facebook/prepack/pull/1806

Differential Revision: D7805532

Pulled By: NTillmann

fbshipit-source-id: 274859e9f6f74ebfc4decc37d984cedcbedf990c
2018-04-28 08:54:20 -07:00
Dominic Gannaway
555e18bb62 Provide better abstract function hints for arrays
Summary:
Release notes: none

This PR provides a mechanism for the React reconciler to understand newly created arrays from maps with unknown properties, in this this first case this is only for `Array.from`, `Object.keys`, `Array.prototype.map`, `Array.prototype.filter`, `Array.prototype.reduce` (with constraints), `Array.prototype.slice` and `Array.prototype.concat`.

When we have something completely abstract, like `props.items`, and it's been wrapped in `Array.from`, we can assume that (in a pure render) that it's safe to emit the `Array.from` and make the array with an unknown property that is an abstract widened hint. The reconciler can see this and perform a nested optimized closure to the map callback.

In cases where the third argument `thisVal` is passed to array methods, we bail-out.
Closes https://github.com/facebook/prepack/pull/1770

Differential Revision: D7795295

Pulled By: trueadm

fbshipit-source-id: 3396330da6d4ebe2ffdd1f1610173eb482df9081
2018-04-27 13:19:57 -07:00
Nikolai Tillmann
c377cba1aa Collect fine-grained statistics on memory usage
Summary:
Release notes: Collect fine-grained statistics on memory usage

This refactoring does a few things:
- Introduce a much nicer `measure` abstract to wrap computations for which we want to measure something
- Measure not only time, but also heap usage
- Project data to legacy statistics file format.
- Limit scope of intermediate serialized information to further reduce memory usage
Closes https://github.com/facebook/prepack/pull/1782

Differential Revision: D7765817

Pulled By: NTillmann

fbshipit-source-id: e6ceb05146490168c379fd8d7d3f1ecffd73db01
2018-04-26 22:41:06 -07:00
Nikolai Tillmann
03719a265a Add --cpuprofilePath FILENAME to serializer test runner
Summary:
Release notes: None

The option works just like for the Prepack CLI.
Closes https://github.com/facebook/prepack/pull/1785

Differential Revision: D7787080

Pulled By: NTillmann

fbshipit-source-id: 04e9cd5b7323e5cf55e1d0ff34a4a3b774df0148
2018-04-26 22:41:05 -07:00
Dominic Gannaway
d38f0570c2 Fixes a bunch of serialization bugs
Summary:
Release notes: none

This PR came about from trying to fix https://github.com/facebook/prepack/issues/1771. This PR fails on the tests still, so I need some help getting them resolved.

- `_emitProperty` should account for the fact a `key` can be an `AbstractValue`, thus needs to serialize the value.
- `visitObjectPropertiesWithComputedNames` in the visitor and `_getNestedAbstractValues` in the serializer both need to take into account cases where `alternate` and `consequent` might not be `AbstractValue`s.
Closes https://github.com/facebook/prepack/pull/1781

Differential Revision: D7777483

Pulled By: trueadm

fbshipit-source-id: 1b94489ec9c800a68414031e0bc63b06061fe559
2018-04-26 14:22:19 -07:00
Dominic Gannaway
9e5cc34819 Fixes an issue with getDerivedStateFromProps
Summary:
Release notes: none

When doing `Object.assign` in `getDerivedStateFromProps`, we need to add back in the fallback for when it might fail otherwise we end up triggering invariants. This fixes https://github.com/facebook/prepack/issues/1773
Closes https://github.com/facebook/prepack/pull/1780

Differential Revision: D7773190

Pulled By: trueadm

fbshipit-source-id: 2539f01cfde3a65136a6e9947a4620dfc81a371a
2018-04-26 01:58:46 -07:00
Dominic Gannaway
fc371688e9 Fix hoisting invariant bug
Summary:
Release notes: none

There was a case where an invariant was firing in the hoisting logic due to a binding value being undefined. This PR stops the invariant from firing in such cases, and includes the regression test. I also found another issue in the evaluatedReactNode debugging output and fixed that too so it was easier to see what was going on with this and other issues.

This fixes https://github.com/facebook/prepack/issues/1775
Closes https://github.com/facebook/prepack/pull/1779

Differential Revision: D7763057

Pulled By: trueadm

fbshipit-source-id: 61c866f7cb7322f5d884262adb85613c97cfa4ca
2018-04-26 01:58:46 -07:00
Dominic Gannaway
d12bcef03e Better handling of this with simple React class components
Summary:
Release notes: none

This fixes bugs around detecting independent dangling `this` keywords in methods of a React class component and correctly bailing out upon finding them. This is typically used in cases where we'd want to bail out, for example:

```js
let self = this;
let handleClick = function () { console.log(self.x) };
return <div onClick={handleClick} />
```

or:

```js
let handleClick = function () { console.log(this.x) };
return <div onClick={handleClick.bind(this)} />
```
Closes https://github.com/facebook/prepack/pull/1777

Differential Revision: D7757435

Pulled By: trueadm

fbshipit-source-id: b06fe29a3ac4a44bdf2b8a7c6e9457e5801b32b7
2018-04-25 04:59:14 -07:00
Dominic Gannaway
2861f78231 Properly strips on* events in first render and fixes tests
Summary:
Release notes: fixes a regression where on* events would not be stripped in React firstRender mode

This PR fixes a recent regression in the stripping of onEvent names in React compiler's firstRender mode. The associated tests have been updated so the snapshots should pick up this regression in the future.
Closes https://github.com/facebook/prepack/pull/1774

Differential Revision: D7747737

Pulled By: trueadm

fbshipit-source-id: e0dd65a7e4d73844c499d1d8b2f9ae8046bfec2b
2018-04-24 13:10:43 -07:00
Dan Abramov
ce6b55916c Add React-related internal regression test to Prepack
Summary:
This adds a React-specific internal test for Prepack to fbsource. It's meant to be land-blocking.

I checked in a manually edited bundle that has no dependencies except `react` and `react-dom` (so it's not too difficult to maintain). I also checked in a snapshot test for what it should render.

The test step consists of running the Jest test (to verify it works *before* Prepack), then using the existing `debug-fb-www` command to produce a bundle, and finally running the same Jest test again.

Currently this only checks the initialization path. When render path serializer bugs are fixed, we can run the same bundle in the render mode as well (and catch further regressions).

Reviewed By: NTillmann

Differential Revision: D7675812

fbshipit-source-id: 99fe3bd700ae3557ee6245f1e8e1e835399625b5
2018-04-23 09:09:00 -07:00
Dominic Gannaway
b798f32ef2 Fold Relay components via createFragmentContainer for firstRenderOnly
Summary:
Release notes: none

This adds the functionality to fold/inline ReactRelay components via `createFragmentContainer`. This is for first-render only for now.
Closes https://github.com/facebook/prepack/pull/1745

Differential Revision: D7686225

Pulled By: trueadm

fbshipit-source-id: 7eb546ff70e92b60bcc1abb69c0cc5091926c012
2018-04-19 14:14:26 -07:00
Dominic Gannaway
9123227e45 Fixes Prettier issues on master
Summary:
Release notes: none

Fixes the current lint issues on master regarding Prettier.
Closes https://github.com/facebook/prepack/pull/1761

Differential Revision: D7686530

Pulled By: trueadm

fbshipit-source-id: 0885854c3cca409d47d4980735f56bd794f55606
2018-04-19 08:53:06 -07:00
Dominic Gannaway
d72ce06580 Support null/undefined config object for React.createElement
Summary:
Release notes: none

When a `null` or `undefined` value is passed as the `config` for `createElement`, then we need to create an empty object to be used instead.
Closes https://github.com/facebook/prepack/pull/1759

Differential Revision: D7686087

Pulled By: trueadm

fbshipit-source-id: a8eb917f38ca3afe881af08d07fe8be0943b0a1f
2018-04-19 07:08:41 -07:00
Dominic Gannaway
d109852ffa Ensure we apply nested closure effects in the right order
Summary:
Release notes: none

Ensure we apply the nested closure effects in the right order. This was the underlying bug after doing much digging.

Furthermore, I added case where this fails. I also found that the ReactElement code was causing issues at one point (I forgot to add the props, type, ref and key as dependencies), but that wasn't needed in the end for this fix, but I thought it best to keep those fixes in.

I also had to make a change to the JSON tester as it was incorrectly failing a test because the function closures were not 1:1, which they're not meant to be.
Closes https://github.com/facebook/prepack/pull/1743

Differential Revision: D7686048

Pulled By: trueadm

fbshipit-source-id: 8cf7faed51c86720e519abbbad209820e7e02dc4
2018-04-19 07:08:40 -07:00