Commit Graph

260 Commits

Author SHA1 Message Date
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
Dominic Gannaway
cb5779c5cd Adds more exclusions to the fb-www lint whitelist
Summary:
Release notes: none

Adds more fb-www lint whitelist exclusions.
Closes https://github.com/facebook/prepack/pull/1746

Differential Revision: D7653846

Pulled By: trueadm

fbshipit-source-id: bf3e47f05bb05d31f223a648e3b920a2acef0d7c
2018-04-17 08:41:52 -07:00
Dominic Gannaway
d811e0c567 Handle cases where gDSFP is given an abstract state
Summary:
Release notes: none

When working on internal projects, I found cases where the `getDerivedStateFromProps` would throw a FatalError because the partial state wasn't an abstract object value or object value. In this case we can see that the abstract value is a conditional and handle the paths to ensure we get the correct results without failing.
Closes https://github.com/facebook/prepack/pull/1737

Differential Revision: D7615094

Pulled By: trueadm

fbshipit-source-id: 5c868a46936a108c277ac52c2675feabc1f4df8c
2018-04-13 03:00:04 -07:00
Nikolai Tillmann
7579c5fc0b Introducting new option --invariantLevel NUMBER and dropping --omitInvariants
Summary:
Release notes: Introducting new option --invariantLevel NUMBER and dropping --omitInvariants

The new default is invariant level 0, which corresponds to the old --omitInvariants.
Level 1 is roughly what we used to do: Check invariants on (derived) abstract values.
Level 2 implements #1180: Checking that all accesses to built-ins do what Prepack expects them to do, including checks for when properties on built-ins are absent.
Level 3 adds checks for internal consistency, basically an internal debug level.

The serializer tests now run with the highest invariant level by default. The added invariants found a few issues that got addressed, including:
- Prepack exposes a TypedArray prototype, which is not a real thing. It's now marked as `__refuseSerialization`, and no invariants are emitted for such things.
- Global variables / properties on the global object are special. Those are not yet handled at level 2.
- Accesses to Prepack magic functions that generally start with `__` should not produce invariant checks.
- Magic code generation for loops should not take into account objects that are `__refuseSerialization`.
- All invariant statements get a unique id to make it easier to locate them.
- I marked some test cases which depend on counting occurrences in the output as "// omit invariants", as the additional invariants increased some such counts.

As part of testing, I also found it necessary to make the --invariantMode more useful; it now also allows specifying nativeLoggingHook which is the preferred way of logging in React Native.

To reduce the number of checks by a few orders of magnitude in practice, each property is only checked on first access. This is tracked by a global variable `__checkedBindings`.

This pull requests incorporates all aspects of the #1709 (which I abandoned).
Closes https://github.com/facebook/prepack/pull/1724

Reviewed By: simonhj

Differential Revision: D7575091

Pulled By: NTillmann

fbshipit-source-id: 585cd224ce66882f8e5f27d88c1ad08afeb96ee1
2018-04-12 11:58:25 -07:00
Dominic Gannaway
cd30805c65 Ensure React component write effects do not conflict one another
Summary:
Release notes: none

This PR adds some sanity around React components roots that when render, mutate the same of bindings as other React component roots. This is currently not supported and thus safely bails out and continues.
Closes https://github.com/facebook/prepack/pull/1736

Differential Revision: D7600373

Pulled By: trueadm

fbshipit-source-id: fe2b2b3055fa3c1b28668da6d67bca3826431eb6
2018-04-12 09:55:14 -07:00
Dominic Gannaway
8264cfffd7 Adds createRef and forwardRef to the React compiler
Summary:
Release notes: Adds`createRef` and `forwardRef` to the React compiler

This PR adds both features from React 16.3, including full inlining of forwardRef functions.
Closes https://github.com/facebook/prepack/pull/1731

Differential Revision: D7599780

Pulled By: trueadm

fbshipit-source-id: 50458546c7a4374baea7fa80feb21262dd5692af
2018-04-12 06:34:44 -07:00
Dominic Gannaway
6ec280b8c8 Adds getDerivedStateFromProps support and updates React version deps
Summary:
Release notes: adds React 16.3 `getDerivedStateFromProps` support to the React compiler

This PR adds support for the React 16.3 `getDerivedStateFromProps` lifecycle event on class components. I've also updated the React testing dependencies to 16.3.1. I also extended the `componentWillMount` logic to support `UNSAFE_componentWillMount` too.
Closes https://github.com/facebook/prepack/pull/1730

Differential Revision: D7586378

Pulled By: trueadm

fbshipit-source-id: 895e74ca86eb9ff9ad04aa93f021c107f08a7b9f
2018-04-11 10:11:33 -07:00
Ariel Mashraki
5bbe3459ee Aggregate common captured scope cases
Summary:
Issues: #995, #1707
Closes https://github.com/facebook/prepack/pull/1721

Differential Revision: D7582788

Pulled By: a8m

fbshipit-source-id: 784189a77f987123069241fbac9dfccc90d0ce6a
2018-04-10 22:39:17 -07:00
Dominic Gannaway
1af47e55e2 Internal bootloader changes
Summary:
Release notes: none

Some internal changes to ensure `Bootloader.loadModules()` global stays as is and doesn't get destructured. Also changed the incorrect usage of `context.$Realm.generator.derive` in the mocks.
Closes https://github.com/facebook/prepack/pull/1726

Differential Revision: D7578301

Pulled By: trueadm

fbshipit-source-id: dd7dce3e46ff01b10eb9206a1ed5d94871ae93fd
2018-04-10 16:10:50 -07:00
Dan Abramov
fae7c44238 Treat fbt as a global object
Summary:
It seems like it's unsafe to rename on www (it breaks Haste) so we should add it to the whitelist of globals.

It's both a function *and* it has properties that are functions, but for now I'll model it as an object since we never use it directly. In fact it seems like www transforms direct calls on it to `fbt._` calls or something like that so maybe keeping it as an object is right. We don't have a single direct call to `fbt()` as a function in our bundle.

This fix unblocks testing the bundle initialization in Jest www environment.
Closes https://github.com/facebook/prepack/pull/1725

Reviewed By: trueadm

Differential Revision: D7568551

Pulled By: gaearon

fbshipit-source-id: bdfc7c949d6be698e1f58a85c1e39f8b6d5b6bae
2018-04-10 08:34:06 -07:00
Nikolai Tillmann
206022a2c9 Fix cycle detection script.
Summary:
Release notes: None

Apparently, Flow does not necessarily report the largest cycle first, which our script assumed.
So now the script looks at all cycles and reports the largest.
Closes https://github.com/facebook/prepack/pull/1693

Differential Revision: D7480758

Pulled By: NTillmann

fbshipit-source-id: 0f55f22ea1442ba1c842ad44db6bf91bd774306d
2018-04-02 22:28:32 -07:00