Commit Graph

656 Commits

Author SHA1 Message Date
Dan Abramov
ec37b77b6e Run Prettier for serializer tests too (#2234)
Summary:
Follow-up to https://github.com/facebook/prepack/pull/2212.
Pull Request resolved: https://github.com/facebook/prepack/pull/2234

Differential Revision: D8788834

Pulled By: gaearon

fbshipit-source-id: 08937736bed3df0ea13d5e7a3925fb2f58633d5c
2018-07-11 03:55:11 -07:00
Herman Venter
8f3ce551f8 Small tweak to solve a pressing instance of a more general problem (#2239)
Summary:
Release note: none

Resolves #2238

This is a quick fix for the above issue. The underlying cause is that we do not construct completions with effects, but rely on incremental updates in special situations, such as the constructor for ForkedAbruptCompletions.

I'll try to fix the underlying cause in a subsequent PR.
Pull Request resolved: https://github.com/facebook/prepack/pull/2239

Differential Revision: D8795886

Pulled By: hermanventer

fbshipit-source-id: 677f2481ae3d6463a73f36a7e7106afbd92b068e
2018-07-10 17:40:29 -07:00
Chris Blappert
91847ea6ba Make optimized functions produce compiler diagnostic on mutating non-… (#2175)
Summary:
…local state

The logic was already there for the React Compiler's invocations of evaluatePure, this PR just generalizes it a little to be used for optmized functions as well.

Additionally, adds the ability to check for compiler info/warning logs in test-runner + updates test-error-handler.

See #1589
Pull Request resolved: https://github.com/facebook/prepack/pull/2175

Differential Revision: D8786744

Pulled By: cblappert

fbshipit-source-id: 110a4732dd6bd129b4d91047c3c9a24f5249a5e9
2018-07-10 12:10:41 -07:00
Chris Blappert
c943ced74e Allow __optimize to work in conditional contexts (#2214)
Summary:
Release Notes: None

Before `__optimize` wouldn't work when called in a conditional context, now if `__optimize` is called in some conditional context, we extract the FunctionValue from the AbstractValue in the `__optimizedFunctions` map.

Also fixes a bug where __optimize would silently noop when given something other than an `ECMAScriptSourceFunctionValue` causing two tests to fail with `TypeError`. Issue #2213 is setup to track this.
Pull Request resolved: https://github.com/facebook/prepack/pull/2214

Differential Revision: D8785643

Pulled By: cblappert

fbshipit-source-id: 3db992d693dd431aa8a2c5e6eb7ad0a1ecb6b79e
2018-07-10 10:34:20 -07:00
Dan Abramov
66351887d3 Run Prettier checks on CI (#2212)
Summary:
This will fail CI if we forgot to run `yarn prettier` before committing.
We do the same in React repo. It prevents committing stale files that later cause unexpected changes.
Pull Request resolved: https://github.com/facebook/prepack/pull/2212

Differential Revision: D8784406

Pulled By: gaearon

fbshipit-source-id: ca948b8e088be8886c8ba865f280ba8d72750f69
2018-07-10 09:55:23 -07:00
Nikolai Tillmann
d456e64116 Add ability to rewrite generated code via global.__output (#2218)
Summary:
Release notes: Add ability to rewrite generated code via global.__output

When a special global variable __output is set to an object,
then all global generator entries are forgotten
and replaced by a series of assignments to reflecting the key-value
pairs of the __output object.

This is needed for instant render to emit single render functions only.
Pull Request resolved: https://github.com/facebook/prepack/pull/2218

Differential Revision: D8778269

Pulled By: NTillmann

fbshipit-source-id: 1dbc5ddd68aa5fd7845da8a7f551c8c7ba2b8919
2018-07-09 19:09:51 -07:00
Dominic Gannaway
db5ed0c7d3 Optimize Object.assign calls by merging the temporal entries together where possible (#2206)
Summary:
Release notes: adds an optimization to Object.assign that attempts to merge calls together where possible

I frequently see `Objet.assign` calls litter our internal bundle. Many of them can actually be merged together to reduce bloat and runtime overhead (on that matter, `Object.assign` isn't a cheap call). We do this by adding a new `TemporalObjectAssignEntry` entry, that allows us to add some fine-tuning of Object.assign temporal entries we create.

The new `TemporalObjectAssignEntry` entry has an optimization that aims to merge entries by checking if linked nodes, specifically the `Object.assign` calls `to` field, to see if it can literally merge the arguments of many `Object.assign`s together. If a `to` is visited and can't be omitted, it doesn't try to apply this optimization. What we end up with, is a single `Object.assign` call and the others all get dead-code eliminated away because of the `mutatesOnly` logic from earlier.
Pull Request resolved: https://github.com/facebook/prepack/pull/2206

Reviewed By: NTillmann

Differential Revision: D8775391

Pulled By: trueadm

fbshipit-source-id: 41e5d6bb1d51fcfff66b2fe758bd51492ec472d9
2018-07-09 16:54:43 -07:00
Caleb Meredith
85b70951d9 Fix React library visiting logic (#2223)
Summary:
> I’m learning the Prepack/React Fusion codebase, so incorrect assumptions and limited a understanding of systems on my part are both very likely.

While I was experimenting with the React Compiler codebase I found the following invariant violation with the test case after that when using `create-element` as the `reactOutput`.

```
Invariant Violation: value must have been visited
```

```js
const React = require("react");

__evaluatePureFunction(() => {
  function Foo(props) {
    return <React.Fragment />;
  }

  __optimizeReactComponentTree(Foo);

  module.exports = Foo;
});
```

[[Prepack REPL]](https://prepack.io/repl.html#MYewdgzgLgBASgUwIbFgXhgJwQRwK4CW2AFAETYpSkCUA3AFD0D6TCAbkgDZ5JQIAKebADE8YVAXDFi1GGgB8MAN70YMAGZiJ4GMJAhiAB0whDEWSrVrsUIWBgAeRJQB0wzEgDmAWwRhYAPTyDGoAvoxqLKZQBN4EAF4IzqgAwiDehuB+UAAq2AjEeiB0ETDeIAAmeJwILggAHpmYUBByuvoMoSVAA)

After digging in more, I discovered that this was the same issue which required some clowniness in the React Compiler tests to workaround.

e3f4262c9d/test/react/setupReactTests.js (L116-L119)

The problem with my example is that the React library was not being visited when a `React.Fragment` appeared even though the serializer needed the library to be visited to output code.

This diff makes sure we visit the React library when we see a `React.Fragment` and makes sure we don’t over visit the React library in `jsx` mode.

I also refactored this area of the code and added comments. Let me know if my refactors or comments don’t make sense.
Pull Request resolved: https://github.com/facebook/prepack/pull/2223

Reviewed By: trueadm

Differential Revision: D8774047

Pulled By: calebmer

fbshipit-source-id: 775a626b8a6bd33a5366e6dae6727350835b060e
2018-07-09 16:04:03 -07:00
Herman Venter
e3f4262c9d Traverse all normal paths when pushing path conditions (#2201)
Summary:
Release note: none

Resolves: #2207

When a PossiblyNormalCompletion has more than one normal path, it is not correct to push only the path leading to the nominally normal completion. Surprisingly, this has not caused all sorts of havoc so far, but clearly this needs fixing.

Interestingly, these changes did uncover some latent bugs, hence the additional changes here.

Testing this more thoroughly will be much easier once PNC composition is fixed. That will take a while, but this PR will help facilitate that.
Pull Request resolved: https://github.com/facebook/prepack/pull/2201

Differential Revision: D8754966

Pulled By: hermanventer

fbshipit-source-id: 220ddc80eaff69b8ee93f75c1943ee1a16adcdee
2018-07-06 15:10:12 -07:00
Herman Venter
7aa5455148 Update test262 submodule hash
Summary: Update the test262 submodule to the latest version.

Reviewed By: cblappert

Differential Revision: D8753974

fbshipit-source-id: 6ba4904969dbe3c529dd73e1d20d227bf6e5c226
2018-07-06 14:25:54 -07:00
Dominic Gannaway
3cd3dd8431 Reduce React bloat on equivalent objects with similar temporal alias trees (#2193)
Summary:
Release notes: none

In an attempt to pull out some of the work from https://github.com/facebook/prepack/pull/2148 to make things easier to consume and review. This PR is one part, where we check the temporal alias values (if an object value has it) and see if we can dedupe the trees. Example below:
Closes https://github.com/facebook/prepack/pull/2193

Differential Revision: D8732542

Pulled By: trueadm

fbshipit-source-id: 352d0048acfef69b5a257c0fe280435fa7baaa7f
2018-07-05 05:09:30 -07:00
Dominic Gannaway
ef7e1873fa Support React keys in array branches, fixes #2139 (#2157)
Summary:
Release notes: none

Add logic to support adding keys when inlining arrays. Fixes https://github.com/facebook/prepack/issues/2139.
Closes https://github.com/facebook/prepack/pull/2157

Differential Revision: D8732339

Pulled By: trueadm

fbshipit-source-id: cfb1fe8725522e3eba5e1061832ddba8359484bb
2018-07-04 08:23:26 -07:00
Dominic Gannaway
2c79cb103d Ensure we handle numeric properties on $GetPartial path (#2205)
Summary:
Release notes: none

We were missing logic for handling abstract arrays with unknown numeric properties when we attempt to get a partial value on the array. I've added a regression test too.
Closes https://github.com/facebook/prepack/pull/2205

Differential Revision: D8732181

Pulled By: trueadm

fbshipit-source-id: 6002eac4b7d4d0b842407a3bb9ea9bcec19f486b
2018-07-04 07:39:05 -07:00
Dominic Gannaway
5f444abbda @allow-large-files [prepack][PR] Adds React native mocks (#2096)
Summary:
Release notes: adds React Native mocks to Prepack

This adds React Native mocks to Prepack and a few basic tests to demonstrate inlining of `View` and `Text`.
Closes https://github.com/facebook/prepack/pull/2096

Differential Revision: D8723932

Pulled By: NTillmann

fbshipit-source-id: 38bd265cd8935ebdf30266ec337378b4ea5b09d6
2018-07-03 14:44:41 -07:00
Sapan Bhatia
e9ef64da0e Support injection of residual statements. Support dynamic invariants. (#2195)
Summary:
Release notes: Support dynamic invariants via __assume

Resolves #2171. Implements an __assume primitive that injects dynamic invariants into the code.

Source:
```js
x = __abstract("number", "5");
__invariant(x==5, "x should be 5");
```

Generated:
```js
(function () {
  var _$0 = this;
  var _0 = 5;
  _$0.x = _0;

  var _1 = _0 == 5;
  if (!_1) {
    throw new Error("x should be 5");
  }
}).call(this);
```
Closes https://github.com/facebook/prepack/pull/2195

Reviewed By: hermanventer

Differential Revision: D8725726

Pulled By: sb98052

fbshipit-source-id: 28db3272199cdb9ae669062344eb82f0ef619bd4
2018-07-03 12:09:49 -07:00
Herman Venter
f12e0369f0 Do not always give up when running Array.map over an abstract array. (#2173)
Summary:
Release note: Enhanced handling of Array.map applied to abstract arrays

Fixes #2169.

If an abstract array is the join or a few concrete arrays, we apply the map over all of the concrete arrays and join the results. This is a bit of a hack, much like what we have for switch statements. The code from the latter has been factored out and reused for this.
Closes https://github.com/facebook/prepack/pull/2173

Differential Revision: D8721507

Pulled By: hermanventer

fbshipit-source-id: e08f2dc1d7e78c7b59f9ff7c76ad54b398b8afe9
2018-07-02 19:23:38 -07:00
Herman Venter
b6ce555f37 Ensure temporal assignments are not lost when the value does not change. (#2197)
Summary:
Release note: Fix temporal assignments to intrinsics that happen inside non deterministic loops

Tweak the property set logic to not short circuit when the target object is intrinsic and the RH value is the same as the current (tracked) property value.

Also fix the code generator for loop bodies to not get upset when the lh side is temporal, but rh side is not widened (because it is a constant).
Closes https://github.com/facebook/prepack/pull/2197

Differential Revision: D8721001

Pulled By: hermanventer

fbshipit-source-id: d38565a40fa7ab8b4e30596f0e1dcfc655a4fb5e
2018-07-02 17:55:04 -07:00
Herman Venter
466d19ddfd Special case "x === undefined || x === null" kind of expressions (#2188)
Summary:
Release note: special case expression simplification for Instant Render

When instant render is enabled turn x === undefined || x === null into __cannotBecomeObject(x) so that Instant Render can easily compile it down to a single byte code.
Closes https://github.com/facebook/prepack/pull/2188

Differential Revision: D8716594

Pulled By: hermanventer

fbshipit-source-id: bbcb25462f79852d8deac29bfed62e86745e5589
2018-07-02 13:39:35 -07:00
Dominic Gannaway
67a47fd48f Improve fb-www mocks objectWithoutProperties value by ensuring we store known values (#2194)
Summary:
Release notes: none

When the `objectWithoutProperties` mock was originally created, my knowledge of Prepack's internals wasn't as good as it was now. Now that I understand how AbstractObjectValues work, we can safely add the known values in `objectWithoutProperties` to the abstract backing object. The backing object was missing these values before and was an empty empty that was partial. This should give more data and value on our internal bundle, where before the values would be lost unnecessarily.
Closes https://github.com/facebook/prepack/pull/2194

Differential Revision: D8716289

Pulled By: trueadm

fbshipit-source-id: 451065473ea09943831f75c0bc15490e73c8d947
2018-07-02 13:11:28 -07:00
Dan Abramov
5159b0d832 Make React tests fast (#2187)
Summary:
Currently we have a single giant file with all tests, and a giant snapshot. This is both slow, and hard to work with and iterate on.

In this PR I will refactor our test setup.

- [x] Split it up into multiple files (gets the test running from 45s to 27s)
- [x] Run Prettier on test files
- [x] Split tests further for better performance
- [x] Make it possible to run one test file
- [x] Fix the issue with double test re-runs in watch mode on changes in the test file
- [x] Refactor error handling
- [x] Run Prettier on fixtures
- [x] Add a fast mode with `yarn test-react-fast <Filename>`
- [x] Fix double reruns on failure

Potential followups:
- [x] Figure out why test interruption broke (need https://github.com/facebook/jest/issues/6599 and https://github.com/facebook/jest/issues/6598 fixed)
- [x] Revisit weird things like `this['React']` assignment with a funny comment in every test
Closes https://github.com/facebook/prepack/pull/2187

Differential Revision: D8713639

Pulled By: gaearon

fbshipit-source-id: 5edbfa4e61610ecafff17c0e5e7f84d44cd51168
2018-07-02 11:25:58 -07:00
Sebastian Markbage
3240eae91b Only havoc abstract value args when really necessary (#2184)
Summary:
Fixes #2179

In #2179 I describe why we might need to havoc some args to abstract values sometimes. This adds an invariant to ensure that we always have args in the cases we need to havoc.

If this abstract value cannot be an object, then we don't need to havoc since there's nothing that can be mutated.

If this has a known values domain, then we know the possible objects. We only need to havoc those, not the args.
Closes https://github.com/facebook/prepack/pull/2184

Differential Revision: D8701601

Pulled By: sebmarkbage

fbshipit-source-id: d5fecbed4cff8013bc768cb6e277094d9ff16d9c
2018-06-29 15:10:22 -07:00
Herman Venter
3deb5e2885 Fix problem with stack location entries (#2183)
Summary:
Release note: Improve source location information

Changes to make sure that the source location of the call expression appears in the corresponding execution context record. Also emit execution records with no source location from stack traces. These are due to calls to internal helper methods for iterating over objects and arrays for argument destructuring.

Finally fix a CompilerDiagnostic construction call to include a source location.
Closes https://github.com/facebook/prepack/pull/2183

Differential Revision: D8698271

Pulled By: hermanventer

fbshipit-source-id: 10f77f718db645a4784723c3eca4bd4e06eb43f8
2018-06-29 11:56:22 -07:00
Dominic Gannaway
9905f613d6 Fixes nested evaluatePure calls and React nested optimized closure side-effect detection (#2166)
Summary:
Release notes: none

Fixes nested `evaluatePure` calls, where before they would collide and overwrite one another. Also ensure React reconciler uses side-effect detection on nested optimized closures. This fixes a React test which should have been failing before, but wasn't.
Closes https://github.com/facebook/prepack/pull/2166

Differential Revision: D8681422

Pulled By: trueadm

fbshipit-source-id: 8941812407d1bda5af0343a09210aeff24a36cff
2018-06-28 13:26:00 -07:00
Dominic Gannaway
7c63a7cd42 Add mutatesOnly feature the generator entries (#2132)
Summary:
Release notes: adds `mutatesOnly` to generator entries to better allow for DCE

This PR adds a new option that can be passed as an optional arg to `generator.deriveAbstract` called `mutatesOnly `. See https://github.com/facebook/prepack/pull/2132#pullrequestreview-130509488 for details. With it, we can better dead-code eliminate generator entries when the value entries that are flagged as mutating are dead code.

The test showing this is below:

Input:
```js
global.f = function() {
  var x = global.__abstract ? global.__abstract({}, "({})") : {};
  global.__makeSimple && __makeSimple(x);
  Object.assign({}, x);
  return 1;
};

if (global.__optimize) __optimize(f);
```

Output (with master):
```js
  var _$2 = this;

  var _$3 = _$2.Object;
  var _$4 = _$3.assign;

  var _0 = function () {
    var _$0 = _$4({}, {});

    return 1;
  };
```

Output (with the changes in this PR):
```js
  var _0 = function () {
    return 1;
  };

  var _2 = function () {
    return global.f();
  };
```
Closes https://github.com/facebook/prepack/pull/2132

Differential Revision: D8667764

Pulled By: trueadm

fbshipit-source-id: 5121da7d73330befeb5a39ea50d7b773256d70bc
2018-06-27 13:09:30 -07:00
Herman Venter
fa4b52f573 Distribute equality checks if that allows simplification (#2174)
Summary:
Release note: More simplification of equality expressions

Resolves issue: #2172

Expressions like (c ? x : y) === null can sometimes be simplified by first rewriting them as (c ? x === null : y === null). Add such a case to the simplifier.
Closes https://github.com/facebook/prepack/pull/2174

Differential Revision: D8666251

Pulled By: hermanventer

fbshipit-source-id: 5b0d56fb091e25bfcdf879be3403cb5a982375ae
2018-06-27 12:10:01 -07:00
Nikolai Tillmann
af010a78db Reviewed all uses of t.memberEpression (#2162)
Summary:
Release notes: None

We used to find random bugs where the `computed` flag wasn't set right.
But even if it's set correctly, we sometimes generated suboptimal code,
e.g. `a["0"]` for an array access.

I reviewed all occurrences of `t.memberExpression`, and redirected all that involve
potentially interesting computations to a new helper function `memberExpressionHelper`
which does "the right thing". This function should always be used.

Added regression test for an array access that used to be suboptimal (observed in InstantRender).
Closes https://github.com/facebook/prepack/pull/2162

Differential Revision: D8625006

Pulled By: NTillmann

fbshipit-source-id: f9211260c08d9195a9f4cc48502cba0794fe84f9
2018-06-25 15:24:19 -07:00
Dominic Gannaway
228c39edf9 Support basic arrow function serialization (#1650)
Summary:
Release notes: adds basic ES2015 arrow function serialization

This allows Prepack to serialize back to arrow functions and also traverse them correctly when understanding `this`.
Closes https://github.com/facebook/prepack/pull/1650

Differential Revision: D8623368

Pulled By: trueadm

fbshipit-source-id: 9be7849770148b67e5f17eee88a633aac906b6e2
2018-06-25 14:09:57 -07:00
Dominic Gannaway
5a5a100483 Provide a basic recovery mechanism for for and while loops (#2118)
Summary:
Release notes: standard for loops and while loops have a recovery mechanism in pure scope

This PR provides a bail-out recovery mechanism in pure scope for FatalErrors thrown and caught from for/while loops. Until now, if a FatalError occurs from trying to evaluate abstract for/while loops, we'd have to recover at a higher point in the callstack, which wasn't always possible (the loop may be at the root of a function/component).

The ideal long-term strategy is to properly model out the different cases for loops, but this is a complex and time-consuming process. This PR adds a recovery mechanism that serializes out the original for loop, but within a newly created wrapper function containing the loop logic and a function call to that newly created function wrapper. This allows us to still run the same code at runtime, where we were unable to evaluate and optimize it at build time.

For now, this PR only adds recovery support for standard `for` and `while` loops (as they go through the same code path). We already have some basic evaluation for `do while` loops, but trying to adapt that code to work with the failing test case (https://github.com/facebook/prepack/issues/2055) didn't work for me – we have so many strange problems to deal with first before we can properly handle that issue.

In cases where the loop uses `this`, the context is found and correctly called with the wrapper function. In cases of usage of `return`, `arguments` and labelled `break/continue` we bail out again as this is not currently supported in the scope of this PR (can be added in a follow up PR, but I wanted to keep the scope of this PR limited).

For example, take this failing case on master:

```js
function fn(props, splitPoint) {
  var text = props.text || "";

  text = text.replace(/\s*$/, "");

  if (splitPoint !== null) {
    while (text[splitPoint - 1] === "\n") {
      splitPoint--;
    }
  }
  return splitPoint;
}
```

This serializes out to:

```js
  var _0 = function (props, splitPoint) {
    var __scope_0 = new Array(1);

    var __get_scope_binding_0 = function (__selector) {
      var __captured;

      switch (__selector) {
        case 0:
          __captured = [_G, _E];
          break;
      }

      __scope_0[__selector] = __captured;
      return __captured;
    };

    var _C = function () {
      var __captured__scope_1 = __scope_0[0] || __get_scope_binding_0(0);

      for (; __captured__scope_1[1][__captured__scope_1[0] - 1] === "\n";) {
        __captured__scope_1[0]--;
      }
    };

    var _$0 = props.text;

    var _$2 = (_$0 || "").replace(/\s*$/, "");

    var _6 = splitPoint !== null;

    var _G = _6 ? void 0 : splitPoint;

    var _E = _6 ? void 0 : _$2;

    if (_6) {
      (__scope_0[0] || __get_scope_binding_0(0))[0] = splitPoint;
      (__scope_0[0] || __get_scope_binding_0(0))[1] = _$2;

      var _$5 = _C();
    }

    var _$6 = (__scope_0[0] || __get_scope_binding_0(0))[0];

    return _$6;
  };
```

Furthermore, an idea that might be a good follow up PR would be to break the wrapper function into two functions, depending on some heuristics. If we can detect that the loop body does not have any unsupported side-effects like writing to variables that are havoced etc, we can then tell Prepack to optimize the inner function wrapper for the loop body. That way, at least some parts of the loop get optimized (the outer bindings will be havoced before this point, so it should work okay). I think I suggested this in person with hermanventer and sebmarkbage in Seattle as a potential way to optimize complex loops that we can't compute the fixed point for right now.

Fixes #2055
Closes https://github.com/facebook/prepack/pull/2118

Differential Revision: D8410341

Pulled By: trueadm

fbshipit-source-id: ee7e6b1bc1feadf0c924e4f82506ca32ca1dadc9
2018-06-25 11:09:37 -07:00
Dominic Gannaway
38392a5499 Slice argument list to fix abstract recovery bug (#2156)
Summary:
Release notes: none

Fixes a bug where the argument list gets mutated and padded with undefined values, so instead we slice it a copy of it so we don't mutate the same array and pass the mutated array instead. Fixes https://github.com/facebook/prepack/issues/2153.
Closes https://github.com/facebook/prepack/pull/2156

Differential Revision: D8610746

Pulled By: trueadm

fbshipit-source-id: 1b6f37693323c813d60f43ab7e9977a99f86ff47
2018-06-25 05:42:27 -07:00
Dominic Gannaway
18e69904d5 Allow Object.assign to continue evaluation in pure scope (#2068)
Summary:
Release notes: in pure mode, allow Object.assign to continue evaluation rather than throwing FatalErrors

This PR adds bail-out support of `Object.assign` sources within the `Object.assign` implementation. This allows us to continue evaluation in pure scope without bailing out of the Object.assign entirely (like we currently do) upon a FatalError occurring. Given we have snapshotting in `Object.assign`, we don't need to havoc the sources.

This allows us to inline and evaluate far more within our internal bundles. Fixes https://github.com/facebook/prepack/issues/2064
Closes https://github.com/facebook/prepack/pull/2068

Differential Revision: D8579441

Pulled By: trueadm

fbshipit-source-id: 0e97b54e0c8af63f1e3cd08fca6c7f375ee3c615
2018-06-21 16:10:40 -07:00
Nikolai Tillmann
d781c5b8ea Leaked declarative bindings are effectively serialized as simple variables (#2125)
Summary:
Release notes: Fixes to leaked declarative bindings

Leaked declarative bindings need to be accessed out-of-band as far
as the serializer is concerned which otherwise only puts final
values into locations.

To make that work, whenever two states are merged where a
declarative binding in one has been leaked but not in the other,
this now gets harmonized by also recording the materialization
side effect into the generator of the other.

The result is that a binding always ends up being fully leaked or not.
For leaked mutable bindings, the tracked value becomes irrelevant, and
is now truly made unavailable. For leaked immutable bindings, the last
value is retained, and we no longer need the strange `leakedImmutableValue` field.

Leaked bindings are now referentialized as simple variables, bypassing the
delayed captured-scope logic. This produces nicer more efficient code, but,
at least for now, has the downside that it rules out sharing of function bodies.

This change is a step towards the (to be publicly documented)
long-term plan to clean up Prepack's handling of leaking and havocing.
(Similar to what this change does for declarative bindings, we'll also must
revisit what happens for leaked object properties. But that's for later.)

This fixes #2122 (issue havocing value in conditional) and adds regression test.
This fixes #2007 (Conceptual issue with havoced bindings) and adds regression test.
Closes https://github.com/facebook/prepack/pull/2125

Differential Revision: D8549299

Pulled By: NTillmann

fbshipit-source-id: 28c3681beafd3890668b72a828f59582c636a6c9
2018-06-20 14:39:53 -07:00
Manas
958fa43d6c test-runner now supports promises (#2115)
Summary:
Release note: none

Attempts adding support for promises in test-runner.js. `inspect` can now return Promises, which will be resolved before checking it value.
Closes https://github.com/facebook/prepack/pull/2115

Differential Revision: D8550825

Pulled By: hermanventer

fbshipit-source-id: 3f9781f6e34016dcb61bd436400a1bfb51932452
2018-06-20 13:55:18 -07:00
Sapan Bhatia
16a74ee72d Tests for the integrity of list operations in optimized functions (#2127)
Summary:
Release notes: none

- Tests on list operations on abstract values
Closes https://github.com/facebook/prepack/pull/2127

Differential Revision: D8545117

Pulled By: sb98052

fbshipit-source-id: cca2bacf340963085a06c191c2fb63effaab21a9
2018-06-20 10:54:59 -07:00
Dominic Gannaway
f2219fd33c Handle intrinsic values created by React that have the same name (#2126)
Summary:
Release notes: none

There was a bug, where React abstract object values with the same intrinsic name were incorrectly being de-duped and re-used. This is a normal expected Prepack optimization, but it actually breaks React components that expect to be able to create many values with the same intrinsic name. We now mark such objects and ensure they do not correctly return `true` from `equals()`. Fixes https://github.com/facebook/prepack/issues/2089
Closes https://github.com/facebook/prepack/pull/2126

Differential Revision: D8448171

Pulled By: trueadm

fbshipit-source-id: d21fddd70576e6e55c41070ac43ce2f58a059e7a
2018-06-15 09:09:45 -07:00
Dominic Gannaway
0cc82dc875 Move ReactElement sanitization to the serialization phase (#2123)
Summary:
Release notes: none

This PR moves the logic of sanitizing ReactElements for `firstRenderOnly` mode to the serialization phase instead of during reconciliation. The plan is to create a follow up PR that introduces a new phase after the visitor phase, that skips values that were detected as dead code once the visitor stage finishes, but that's not in scope for this PR.
Closes https://github.com/facebook/prepack/pull/2123

Differential Revision: D8435440

Pulled By: trueadm

fbshipit-source-id: f442525e663a7bc0f9608b96eb7d7a2389a707b7
2018-06-15 06:53:25 -07:00
Dominic Gannaway
491ec2ad26 Adds regression tests for issue 2056 (#2124)
Summary:
Release notes: none

It turns out that the tests in https://github.com/facebook/prepack/issues/2056 now pass on master, so this adds regression tests for them. Fixes #2056.
Closes https://github.com/facebook/prepack/pull/2124

Differential Revision: D8432504

Pulled By: trueadm

fbshipit-source-id: fce78b4ecfc9cee55cf70868557a3eacac635867
2018-06-14 16:03:18 -07:00
Dominic Gannaway
0d7807d871 Nested functions bindings (#2117)
Summary:
Release notes: fixes serialization of bindings when shared between optimized functions

This PR fixes a long standing bug with nested optimized functions where bindings would incorrectly serialize to the main body scope when the binding was shared between nested optimized functions and their parent optimized function scopes. This allows us to not skip 2 React tests and I also added a serializer regression test that demonstrates the same problem so we don't regress.
Closes https://github.com/facebook/prepack/pull/2117

Differential Revision: D8408712

Pulled By: trueadm

fbshipit-source-id: 0e0a306f9195fcb5b57fa7f8cef1c65dbef4998f
2018-06-13 16:27:32 -07:00
Dominic Gannaway
3bd3ecc072 Support logical operator unfolding in React reconcilation (#2091)
Summary:
Release notes: React compiler supports unfolding && and || logical expressions

This adds support for `&&` and `||` logical abstract value unfolding.
Closes https://github.com/facebook/prepack/pull/2091

Differential Revision: D8386493

Pulled By: trueadm

fbshipit-source-id: 3def85ac912906ada087a99c27f91ad80897c55e
2018-06-12 18:28:04 -07:00
Dominic Gannaway
9c11ec9a5e Use isPure and isInvariant in many temporals (#2097)
Summary:
Release notes: none

When we create temporals that are pure, let's mark them as pure and also skip creating invariants for them too. Making these changes allows the serializer to not emit temporals that never end up getting used, reducing the output and also making it easier to debug the output (less spam of temporals).
Closes https://github.com/facebook/prepack/pull/2097

Differential Revision: D8329043

Pulled By: trueadm

fbshipit-source-id: f1ef4185793115dd7982b8162a7e3dc4038a15f9
2018-06-12 18:19:57 -07:00
Dominic Gannaway
0d762f7ab5 Add lazy ReactElement creation when in conditionals (#2107)
Summary:
Release notes: none

This is a long standing fix, where ReactElements should be created lazily but are currently not done so. To do this, we now use the `temporalAlias` code paths on lazy branched ReactElements to ensure they are emitted as temporal entries when we "branch" (i.e. conditional) and have many possible routes where ReactElements may or may not be created.

Fixes https://github.com/facebook/prepack/issues/2113. Depends on https://github.com/facebook/prepack/pull/2112
Closes https://github.com/facebook/prepack/pull/2107

Differential Revision: D8383327

Pulled By: trueadm

fbshipit-source-id: bbcff45ddd07406b18bcddce2de0279fb52da1a1
2018-06-12 12:39:43 -07:00
Dominic Gannaway
05a7730b99 Optimize ReactElement children with equivalence logic (#2114)
Summary:
Release notes: improves ReactElement creation by re-using ReactElement nodes where possible

We already have a pretty good ReactElement equivalence system to re-use ReactElements. We weren't using it to its full power though. When we have nested ReactElements, we don't use the equivalence system at all, meaning we duplicate lots of ReactElements when we can re-use.

This is a nice performance optimization. I've added a test that should prevent regressions here too.
Closes https://github.com/facebook/prepack/pull/2114

Differential Revision: D8381595

Pulled By: trueadm

fbshipit-source-id: befabd04326a162f8ab6a00e089cdada052cf6c8
2018-06-12 11:09:19 -07:00
Dominic Gannaway
e4875197fb Improve inlining of React.createContext (#2098)
Summary:
Release notes: none

Whilst working on adding React Native mocks, I ran into cases where context should be inlining but it wasn't. It now is inlining far better, with more test coverage. Furthermore, we now have a new config flag to pass to `__optimizeReactComponentTree`, in the case of `isRoot` to state that the tree is a root component tree (rather than a a branch of another tree).
Closes https://github.com/facebook/prepack/pull/2098

Differential Revision: D8348381

Pulled By: trueadm

fbshipit-source-id: 5e01bd77437e8bc3d1f22ff47d668897152203a0
2018-06-11 04:36:50 -07:00
Dan Abramov
2cd33523bf Remove a hacky global for context tests (#2102)
Summary:
The code didn't work without it sometimes because conceptually all code outside of `getTrials` is an isolated "bundle". We can only access its internals through the `Root` reference. This fixes the tests to follow this constraint and removes the hack.
Closes https://github.com/facebook/prepack/pull/2102

Differential Revision: D8333634

Pulled By: gaearon

fbshipit-source-id: 1fb24751490042beae55a133f64351a9be9f903c
2018-06-08 10:24:52 -07:00
Manas
e24f02d5ab Fix class serialization test (#2100)
Summary:
Release note: none

Fixes a class serialisation test.
Closes https://github.com/facebook/prepack/pull/2100

Differential Revision: D8331997

Pulled By: trueadm

fbshipit-source-id: 9b3624e817a6bfa961ae4d1e494eea6ac7603c4b
2018-06-08 07:08:55 -07:00
Roman Khotsyn
297e942a42 Fixing invalid code generation for abstract member access (#2084) (#2093)
Summary:
There is a case when prepack emits non-computed member expressions in `rebuildObjectProperty` for properties which cannot be used this way. This PR is to fix #2084 .
Closes https://github.com/facebook/prepack/pull/2093

Differential Revision: D8319018

Pulled By: hotsnr

fbshipit-source-id: a27b943b541f6210d44c1e9a5887915eec5c6359
2018-06-07 13:16:56 -07:00
Dominic Gannaway
c551500aeb Call React createDefaultPropsHelper creates function on init (#2087)
Summary:
Release notes: none

This fixes an issue where `createDefaultPropsHelper` gets created in a branch of effects, and is cached on the `realm`. Instead `createDefaultPropsHelper` should get created during the init phase, so the function is accessible throughout the entire lifecycle of the realm.
Closes https://github.com/facebook/prepack/pull/2087

Differential Revision: D8290010

Pulled By: trueadm

fbshipit-source-id: 324035cdd3c8a951c44849e1ccbfca9798a551b0
2018-06-05 17:54:45 -07:00
Herman Venter
0703a1b290 Remove code that is no longer needed. (#2077)
Summary:
Release note: none

Deletes some code that is no longer needed.
Closes https://github.com/facebook/prepack/pull/2077

Differential Revision: D8272617

Pulled By: hermanventer

fbshipit-source-id: a6a715da55846a7feb29dade8bd6146735b94913
2018-06-04 20:57:42 -07:00
Dominic Gannaway
318da6c7f6 Refactor of createElement props/config to fix bugs + use snapshotting
Summary:
Release notes: fixes a range of spread bugs with ReactElements

This is a very important PR for React reconciliation, it fixes many undiscovered bugs and adds a huge amount of test coverage that was previously missing.

Whilst testing quite complex cases of JSX spreads in combination with defaultProps on our internal bundle I noticed that there were some bugs appearing, but because the branches where these bugs were appearing were not used on firstRender, it meant we got away with it on our internal tests.

We now use snapshotting and properly evaluateForEffects when recovering from `Object.assign` with ReactElement creation of config/props. We also properly use the `temporalAlias` to ensure we reference the correct object.
Closes https://github.com/facebook/prepack/pull/2070

Differential Revision: D8243793

Pulled By: trueadm

fbshipit-source-id: e8c37aa6750c0a6d41f12249d8872004da3ab3a6
2018-06-02 06:34:27 -07:00
Nikolai Tillmann
51a3c47836 Properly havoc object property bindings that might have been deleted.
Summary:
Release notes: None

This fixes #2067.

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

Differential Revision: D8243118

Pulled By: NTillmann

fbshipit-source-id: e6ddc6f45d60f1a7579d38a73f22c5a0950a877f
2018-06-01 16:25:09 -07:00
Dominic Gannaway
7bfd0d1fd9 Fix #2051 and handle all Array.prototype methods for unknown arrays
Summary:
Release notes:

This PR is a follow up to https://github.com/facebook/prepack/pull/2051, which we found to have issues and had to be reverted. The main cause of the issue in the previous PR was that `realm.evaluateWithAbstractConditional` was being given a `ReturnCompletion`, which are a type of `AbruptCompletion`. There is logic to correctly throw such completions. So instead of passing a `ReturnCompletion` to `realm.evaluateWithAbstractConditional`, we instead pass the value and then wrap the `realm.evaluateWithAbstractConditional` call with a function that adds back on the `ReturnCompletion`.

Fixing this brought about a bunch of deeper issues that were causing tests to fail (regression tests added) around the unknown array and its prototype methods. We were only handling a handful of methods before, but that was fragile. So this PR now adds support for all the of current prototype methods on `Array` for unknown arrays – following the spec as to what the return value should be in each case.

Finally, a change was made to the React reconciler to ensure that we return the unknown array in cases where it is passed an unknown array without a ReactHint (which is expected, but was missed and thus a regression from a previous PR).
Closes https://github.com/facebook/prepack/pull/2061

Differential Revision: D8229848

Pulled By: trueadm

fbshipit-source-id: 02dbd1c7e1cd03de4f6745daed57d13ea24537a8
2018-05-31 17:04:35 -07:00
Dan Abramov
9725823d4f Add regression tests for #1837, #1840, and #1848
Summary:
Since #1837 and #1848 got fixed at some point, this adds tests to verify they don't regress.
Closes https://github.com/facebook/prepack/pull/2066

Differential Revision: D8221658

Pulled By: gaearon

fbshipit-source-id: a31fc733964ae697252225993b813e8d5a445ed1
2018-05-31 08:23:02 -07:00
Dominic Gannaway
bcf7255ce3 Do not emit final property assignments when havocing
Summary:
Release notes: none

When in strict mode, emitting property assignments to a frozen object (ReactElement in this case) causes a runtime error. We shouldn't be emitting ReactElement properties when we havoc the object. Unfortunately, we can't do this to all final objects, because our internal snapshot test fails when doing this (because the final object has properties that are conditional and thus delayed, so we need all its bindings to be "flushed" at the point of havocing). As a more thorough future fix, we should probably add a separate codepath for serializing objects that are final (we delay the entire object being emitted until all its properties are ready, like the ReactElement serializer does).

Interestingly, the output contains an unused variable that should be removed NTillmann?

```js
var _0 = function (props, context) {
    "use strict";

    var _J = props;
    var _$0 = _J.b;

    var _1 = _$0 !== null;

    if (_1) {
      var _$1 = _J.b;
      var _$2 = _$1.x;

      var _5 = _$2 !== null;

      if (_5) {
        var _$3 = _J.b;
        var _$4 = _$3.x;
      }
    }

    var _$5 = _J.c;
    var _$6 = _J.someAbstractFunction;

    var _A = _1 ? _5 ? _$4 : null : null;

    var _8 = {  // <-- why has this not been removed? can we not mark the entry as "pure"
      a: 1,
      b: _A,
      c: _$5
    };
    _8.a = 1;
    _8.b = _A;
    _8.c = _$5;

    var _F = <div a={1} b={_A} c={_$5} />;

    var _$7 = props.someAbstractFunction(_F);

    return _F;
  };
```
Closes https://github.com/facebook/prepack/pull/2065

Differential Revision: D8221498

Pulled By: trueadm

fbshipit-source-id: e508cba2e930bec9c913efae3c653637671098c6
2018-05-31 07:27:44 -07:00
Herman Venter
bb12168a0d Make joinPossiblyNormalCompletionWithAbruptCompletion live up to its advertised behavior
Summary:
Release note: none

joinPossiblyNormalCompletionWithAbruptCompletion said that it always returned effects with completions of type JoinedAbruptCompletions. Some callers took it at is word. Turns out it was lying.

Fixed things so that the advertising is correct. Also fixed an issue with a generator being lost during joining. (This was a latent bug uncovered by this fix.)

Refactored the code that fails when a loop body contains both break and continue completions governed by abstract conditions.
Closes https://github.com/facebook/prepack/pull/2030

Reviewed By: trueadm

Differential Revision: D8188966

Pulled By: gaearon

fbshipit-source-id: 7b74d63ee34b6492614a4386e6ad7955c96cbf78
2018-05-31 06:51:12 -07:00
Nikolai Tillmann
0b0b675fbd A step forward towards fixing havocing object property bindings.
Summary:
Release notes: Improvements towards fully supporting havocing object property bindings.

This fixes #2013 and fixes #2017.

There are varios TODOs in the new code; whatever didn't violate any existing tests throws a FatalError,
while the other cases still silently do the wrong thing.
Once this PR lands, I'll file issues for the various TODOs which can then be worked on separately.
In any case, the changes in this PR are strictly making things better.

Adding regression tests from the fixed issues.
Closes https://github.com/facebook/prepack/pull/2023

Reviewed By: trueadm

Differential Revision: D8174176

Pulled By: NTillmann

fbshipit-source-id: 299af8546ea7474a67fc0d75ce6ad8649b060db7
2018-05-30 16:02:06 -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
Dan Abramov
f55285012e Back out "[prepack][PR] Support call expressions where the base might be an abstract conditional"
Summary: It caused some regressions but we're not sure why. Need to increase test coverage first. Reverting for now.

Reviewed By: trueadm

Differential Revision: D8205062

fbshipit-source-id: fe03f8ea9e8c3d85b3ce96912c5135019f407a56
2018-05-30 09:45:00 -07:00
Dominic Gannaway
24181252fe Support call expressions where the base might be an abstract conditional
Summary:
Release notes: support call expressions where the base might be an abstract conditional

This PR is a follow up on a TODO I left in last week. We currently don't fully use the power of Prepack  around abstract conditional function calls. This adds support for them when calling NativeFunctionValues. For example:

```js
function fn(a)  {
  var array = (a === null ? [1,2,3] : [4,5,6]);

  return array.join("-");
}

global.__optimize && __optimize(fn);
```

Now becomes:

```js
  var _1 = function (a) {
    return a === null ? "1-2-3" : "4-5-6";
  };
```

Beforehand, it compiled to:

```js
  var _1 = function (a) {
    var _$0 = (a === null ? [1, 2, 3] : [4, 5, 6]).join("-");

    return _$0;
  };
```
Closes https://github.com/facebook/prepack/pull/2051

Differential Revision: D8201793

Pulled By: trueadm

fbshipit-source-id: c9a570ef9da844d84d0d5548b5c2d7b600dd4226
2018-05-30 04:10:08 -07:00
Nadav Kaner
45750d84ad remove verbose error when invariant level is zero
Summary:
Release Note: none

fix #1893
remove verbose error when invariant level is zero
Closes https://github.com/facebook/prepack/pull/2038

Differential Revision: D8180698

Pulled By: NTillmann

fbshipit-source-id: e0f9504ef84215292a9b4182d23d0898e7ef6c32
2018-05-28 16:56:15 -07:00
Nikolai Tillmann
459f3dc802 Mutations of final objects are not allowed.
Summary:
Release notes: None

This fixes #2040.
Adding regression error handler test.
Closes https://github.com/facebook/prepack/pull/2042

Differential Revision: D8180569

Pulled By: NTillmann

fbshipit-source-id: 2fd2dff79a8d78db91e8d089df44476083e66b89
2018-05-28 15:22:30 -07:00
Nikolai Tillmann
2cf7e98cb2 Adding regression test for #2015.
Summary:
Release notes: None

This closes #2015.
Adding regression test, as this was fixed by #2008 and #2010.
Closes https://github.com/facebook/prepack/pull/2035

Differential Revision: D8177974

Pulled By: NTillmann

fbshipit-source-id: dcc014f57a7d3e6ad42ed1c61535b6991e06bbde
2018-05-27 14:21:12 -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
Nikolai Tillmann
62636d4b2a When havocing immutable bindings, keep around and later use the leaked value
Summary:
Release notes: None

Adding regression test.
While this really just does something for const bindings that we probably don't care much about,
this is leading up to a similar change for final objects which is much more relevant.

(And eventually, the last known value of a havoced mutable binding and havoced non-final objects in between external calls should be handled in this way as well.)
Closes https://github.com/facebook/prepack/pull/2031

Differential Revision: D8172560

Pulled By: NTillmann

fbshipit-source-id: 4e839113d7e5cd0f676e0017dd774da82b6dcdcf
2018-05-25 18:04:09 -07:00
Dominic Gannaway
531b4972da Better support indexOf and reverse on unknown arrays with numeric properties
Summary:
Release notes: support `indexOf` and `reverse` on unknown arrays with numeric properties

This PR aims to better support `indexOf` and `reverse` on unknown arrays with numeric properties. Previously, these two methods on the array would cause a FatalError in pure mode that would recover and havoc the array itself and the arguments. I don't believe this is necessary for these two methods in pure mode because they don't mutate the arguments passed. In pure mode we expect that calling `toString` on the arguments won't affect global scope, so these operations should be fine to be emitted as temporals with them being havoced.

I also added a TODO to an area I want to look at next week that I feel will unlock many more optimizations and inlining possibilities (with regards to handling conditional abstract objects as the context of the function call).
Closes https://github.com/facebook/prepack/pull/2033

Differential Revision: D8172837

Pulled By: trueadm

fbshipit-source-id: 846e28c0e0a6d0d475ad6ba6ef705bf0eae55b85
2018-05-25 17:25:18 -07:00
Dominic Gannaway
3ec7ef254c Fix havoc bindings regression
Summary:
Release notes: none

Was a mistake on the original PR. Fixes https://github.com/facebook/prepack/issues/2032
Closes https://github.com/facebook/prepack/pull/2034

Differential Revision: D8172823

Pulled By: trueadm

fbshipit-source-id: 734c026331c78497f7261228f4c1995619fbc5bd
2018-05-25 17:10:42 -07:00
Dominic Gannaway
7a8dba42e9 Add Prepack __makeFinal global helper
Summary:
Release notes: adds a `__makeFinal` Prepack global helper

This is to be used in follow up PR tests.
Closes https://github.com/facebook/prepack/pull/2029

Differential Revision: D8164904

Pulled By: trueadm

fbshipit-source-id: 3f167ff683235e6e083467818ad6a489619205cc
2018-05-25 11:11:00 -07:00
Nikolai Tillmann
01ab307aa8 Fixing binding value after havocing
Summary:
Release notes: Fixing havocing of bindings.

This fixes #1973 and it fixes #2003.

When havocing a binding,
the binding's value at that point in time would remain in the binding,
and participate in the whole value merging process,
which was meant to compute final values and caused issues.

To fix this, an explicit assignment is now emitted at binding havocing time with the current binding value, and afterwards, the current binding value, which is irrelevant from then on, is set to undefined.

This effectively fixes the issue for bindings, but the whole way binding havocing works is a bit inefficient (after havocing, Prepack effectively stops tracking that binding); even worse, similar problems that we observed here for bindings should exist for object properties as well; and the generated code looks a bit awful. I'll follow up creating separate issues for those, but they are out of scope for this change.

Adding regression tests.
Closes https://github.com/facebook/prepack/pull/2010

Differential Revision: D8153779

Pulled By: NTillmann

fbshipit-source-id: 9d64980e0bf2c8afe018ba0814907b90d19a9f77
2018-05-24 18:27:55 -07:00
Nikolai Tillmann
e24b90aeec Havoc all the bindings, deal with havoced bindings that get assigned to.
Summary:
Release notes: None

This fixes #2001: `let` bindings didn't get properly havoced,
and things could got generally wrong when dealing with havoced bindings that get assigned to.
This fixes those basic issues, strictly making things better.

However, havoced bindings in general remains a conceptually flawed feature
as described in #2007.

Adding a few regression tests.
Closes https://github.com/facebook/prepack/pull/2008

Differential Revision: D8148798

Pulled By: NTillmann

fbshipit-source-id: 34b821915bb5f0416ac55b4e347f956959ae0594
2018-05-24 12:35:25 -07:00
Dominic Gannaway
75dfdea8d2 Havoc unknown array values
Summary:
Release notes: none

This was missed off when we created unknown array values. This makes it so they can be havoced.
Closes https://github.com/facebook/prepack/pull/2016

Differential Revision: D8139928

Pulled By: trueadm

fbshipit-source-id: e0ec54fe573f6b6b7f4e44f04d08a2d23976ed0a
2018-05-24 06:24:56 -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
Sapan Bhatia
373c6d917d Fix nit that crept through
Summary:
This line that refers to a missing variable slipped though a previous commit.
Closes https://github.com/facebook/prepack/pull/1988

Reviewed By: trueadm

Differential Revision: D8105162

Pulled By: sb98052

fbshipit-source-id: 6e35b882f0af94c2acd8096f955bd9ab7275ed77
2018-05-22 15:54:22 -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
b6536991b0 Stack completion saved effects
Summary:
Release note: none

When forking the normal branch of a PossiblyNormalCompletion into yet another PossiblyNormalCompletion, push the current effects onto a stack of effects, rather than just continuing to use the currently active effects. Not doing so, causes mismatched undo operations.

The modified test case would fail and print 2 for y, without this change.
Closes https://github.com/facebook/prepack/pull/1993

Differential Revision: D8087175

Pulled By: hermanventer

fbshipit-source-id: 6b857b9885aa79a8e90b90e365a2b9688a34152d
2018-05-21 21:55:56 -07:00
Nikolai Tillmann
9c26f640ab Support for --delayInitializations for optimized functions
Summary:
Release notes: Support for --delayInitializations for optimized functions

Supporting this removes a TODO and is in response to #1973 (although more of a work-around than the actual fix).

Added tests.
Closes https://github.com/facebook/prepack/pull/1994

Differential Revision: D8087001

Pulled By: NTillmann

fbshipit-source-id: 572f41ffc024bef7954ebd88068f350fe08a84dc
2018-05-21 21:07:57 -07:00
Tim Seckinger
dd63339992 fix: coerce abstract values into strings for the Error constructor
Summary:
Release Notes: Fix abstract values not being coerced into strings for the Error constructor

Fixes #1827 NTillmann
The exact example from the issue now prepacks to
```javascript
(function () {
  var _0 = function () {
    return 42;
  };

  inspect = _0;
})();
```

I'm new here, so if this approach is completely wrong, please do notify me and guide me the way to a better one ;)
Closes https://github.com/facebook/prepack/pull/1960

Differential Revision: D8043199

Pulled By: NTillmann

fbshipit-source-id: 9c67fc2ab882398a20e6313b2894b5357b5ef038
2018-05-21 15:58:33 -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
Herman Venter
21cb2b4da5 Avoid redundant conversions to object
Summary:
Release note: none

When debugging another issue, I noticed that member expressions do explicit conversions of abstract base objects to object and that call expressions obtain a temporal value for the function but then go ahead without it, leaving a useless assignment in the timeline.
Closes https://github.com/facebook/prepack/pull/1983

Reviewed By: trueadm

Differential Revision: D8055038

Pulled By: hermanventer

fbshipit-source-id: 4dd394bb0c4df2f9656be453b8feae57cc0db516
2018-05-18 01:19:22 -07:00
Dominic Gannaway
da243f5b48 Fix bug with arrays with widened numeric properties
Summary:
Release notes: none

This PR fixes a bug where prototype methods on unknown arrays with widened numeric properties were incorrectly being used instead of following the route to filter which methods were safe or not. The functionality and logic for this was pulled out, into its own function so it can be re-used in places and tidied up.
Closes https://github.com/facebook/prepack/pull/1981

Differential Revision: D8043347

Pulled By: trueadm

fbshipit-source-id: 05415e5bdcb85818681a72323df16711a89f7c5c
2018-05-17 14:22:26 -07:00
Herman Venter
529ea0d760 Don't rotate effects trees
Summary:
Release note: fix numerous problems with code ordering
Closes: #1914

We've been seeing an endless stream of bugs where code is either missing or in the wrong place. A lot of these were due to the complexity of joinEffectsAndPromoteNested and some more are due to a fundamental flaw in its algorithm: it rotates branches of the effects tree in order to group together all completions of a given type. That can cause generators to end up in the wrong place in the temporal sequence.

We also had a problem with generators being duplicated in the tree.

This pull request introduces a new algorithm for doing what joinEffectsAndPromoteNested does. This too is complicated and I spent days on debugging and fixing many subtle issues. So, for now, I'm only doing it for calls. More will come in later pull requests.

I am not super confident that I've found and addressed all subtle bugs. I think we can expect to run into quite a few more of those. I am, however, reasonably confident that we now have the right approach to dealing with abrupt control flow.

Please have a careful look, but let's get this landed as soon as possible because it is on the critical path.
Closes https://github.com/facebook/prepack/pull/1979

Differential Revision: D8044482

Pulled By: hermanventer

fbshipit-source-id: 317402c5601fdea7366c9daf7762af0217302b54
2018-05-17 11:45:18 -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
Xun Li
1f02f31308 Fix issue #1841.
Summary:
When either name or msg of Error is abstract, we do not want to partially evaluate it because the checks on string emptiness can be overwhelming, and better done in the VM than in JS.
Added a test to check these cases.
(I messed up my previous pull request. Sending a new one here.)
Closes https://github.com/facebook/prepack/pull/1974

Differential Revision: D8028508

Pulled By: lxfind

fbshipit-source-id: 8e1d1f2151e0b08b519935387298d4ffcd579f9b
2018-05-16 11:56:50 -07:00
Tim Seckinger
5df51ac6f4 stop the prototype cycle check if an object uses non-ordinary prototype methods
Summary:
Release Notes: stop the prototype cycle check if an object (e.g. proxy) uses non-ordinary prototype methods

Fixes #1017
Closes https://github.com/facebook/prepack/pull/1976

Differential Revision: D8027102

Pulled By: NTillmann

fbshipit-source-id: 886e6ce474255dadf937662e30a65adbfac5a1f1
2018-05-16 11:06:51 -07:00
Dominic Gannaway
f807a17b74 Further follow-up Array.from fixes
Summary:
Release notes: none

This is a follow up to the changes in https://github.com/facebook/prepack/pull/1926. This PR correctly fixes the derived values for waiting and ensures that the unknown array objects have their dependencies properly resolved. This fixes part of the issue in https://github.com/facebook/prepack/issues/1962, but it brought about another issue that this PR doesn't aim to solve – dependencies on an abstract function call's unbound/bound bindings.
Closes https://github.com/facebook/prepack/pull/1970

Differential Revision: D8024402

Pulled By: trueadm

fbshipit-source-id: b9f9e725b7b22241209ef5a6f3b29dc0f2eeddeb
2018-05-16 05:15:03 -07:00
Nikolai Tillmann
ea0624b108 Distribute conditionals in certain relational expressions
Summary:
Release notes: More simplification rules

The existing simplifier would never go into relational expressions
and distribute conditional expressions. It does now.

With this change, `AbstractValue.createFromBinaryOp` joins many other
value factory functions that may return non-abstract values.

This caused various changes downstream in types, and dealing with concrete
instead of abstract values.

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

Differential Revision: D8023363

Pulled By: NTillmann

fbshipit-source-id: a3cd6f7752ba24d039c6085bec2ee93f7587af26
2018-05-15 23:56:32 -07:00
Nikolai Tillmann
6b3866885f Fixing AbstractObjectValue's $Get
Summary:
Release notes: None

It used to bail out for conditional abstract values when accessing
a prototype that existed on neither side of the condition. No more.
Also, things used to be wrong in the presence of object prototypes.
That's also getting fixed.

Adding regression tests.
Closes https://github.com/facebook/prepack/pull/1963

Differential Revision: D8000539

Pulled By: NTillmann

fbshipit-source-id: 5214f213ea49c63e9637126360d3c90aace92d20
2018-05-14 18:03:46 -07:00
Nikolai Tillmann
ad9ed9ba97 Don't treat original constructor specially in the visitor.
Summary:
Release notes: None

This fixes #1957.
Turns out that the special case is no longer needed, and just removing that code fixes the issue now.
Adding regression test.
Closes https://github.com/facebook/prepack/pull/1958

Differential Revision: D7995563

Pulled By: NTillmann

fbshipit-source-id: 6822c5433679fd88bd5a052ca23824cb3f3eabba
2018-05-14 13:55:47 -07:00
Herman Venter
770bfef8ca Objects that are temporal should set _isScopedTemplate to true
Summary:
Release note: Fixes problem with result of Array.filter (and similar) applied to arrays with unknown properties

Closes: #1924

Generator.deriveConcrete can result in temporal object values. These must be marked with _isScopedTemplate to prevent them from being hoisted.
Closes https://github.com/facebook/prepack/pull/1926

Reviewed By: trueadm

Differential Revision: D7949463

Pulled By: hermanventer

fbshipit-source-id: 2f15117725c37e9b09cae8ac469ee5b2eb481b6c
2018-05-14 13:55:46 -07:00
Nikolai Tillmann
9685f866ce Fix frozen lazy objects
Summary:
Release notes: None

The `Object.freeze` command (or similar) was put into the body
where the object was allocated, not where it got initialized.
This would cause the initialization code to silently fail later on when the object was used for the first time.

This fixes it, and adds a regression test.
Closes https://github.com/facebook/prepack/pull/1936

Differential Revision: D7994911

Pulled By: NTillmann

fbshipit-source-id: 6ec0706357706f7bf80f62690be9aea1f30f8a72
2018-05-14 13:05:44 -07:00
Dan Abramov
b594b283c2 Don't treat makePartial() as a mutation in havoc checker
Summary:
Fixes https://github.com/facebook/prepack/issues/1931.

The issue is that this call may happen on a havoced object:

41e9dcb398/src/intrinsics/ecma262/Object.js (L98-L100)

That fails. But I'm not sure it makes sense to even check havocing for internal properties like `_isPartial_binding`.

Maybe there's a deeper problem here. I don't see it but at least this gets the ball rolling.
Closes https://github.com/facebook/prepack/pull/1955

Differential Revision: D7992958

Pulled By: gaearon

fbshipit-source-id: 3e843ae159896c15b8f9dc2fd6956b148a2ef44f
2018-05-14 11:59:52 -07:00
Dan Abramov
200b5c5f59 Conditional return completions might need to be dereferenced
Summary:
Fixes https://github.com/facebook/prepack/issues/1953.

We used to delegate handling of conditional expression to `IfStatement`. But this is not entirely accurate because conditional expression completion might be an identifier. `IfStatement` rules are too restrictive.

I copy pasted the code from IfStatement and added `GetValue` dereferencing [to match the specification](http://www.ecma-international.org/ecma-262/7.0/#sec-conditional-operator-runtime-semantics-evaluation). I also removed `UpdateEmpty()` calls which seem to only be relevant to `IfStatement` evaluation.

Adds a regression test.
Closes https://github.com/facebook/prepack/pull/1954

Differential Revision: D7988920

Pulled By: gaearon

fbshipit-source-id: ac130076dbaa04d5d661adb984b408b4d3b57fa3
2018-05-14 08:09:16 -07:00
Dan
41e9dcb398 Fix havoc logic for conditional abstracts
Summary:
Fixes https://github.com/facebook/prepack/issues/1883.

As I noted there,

>This seems to happen because the logic in `visitObjectPropertiesWithComputedNames` hasn't been updated in the same way that [its twin in the residual heap visitor has been](aa700a2667/src/serializer/ResidualHeapVisitor.js (L361-L388)).

This brings them in line.

Regression case included. It used to fail with bad output even after this change, but https://github.com/facebook/prepack/pull/1937 fixed that, so now it passes.
Closes https://github.com/facebook/prepack/pull/1942

Reviewed By: trueadm

Differential Revision: D7987993

Pulled By: gaearon

fbshipit-source-id: 1ebda0c38f2f932aa18872bfc9a919938fc2ef96
2018-05-14 02:52:09 -07:00
Dan Abramov
20683624ab Put EmptyValue into correct join branch
Summary:
Fixes https://github.com/facebook/prepack/issues/1935.
The issue was that we'd always put `EmptyValue` into the right branch even if it happened in the left one.

Adds a regression test.
Closes https://github.com/facebook/prepack/pull/1937

Reviewed By: trueadm

Differential Revision: D7967344

Pulled By: gaearon

fbshipit-source-id: ece8550787679e2fc33f040989ceae0cf3a7c2a2
2018-05-11 07:07:02 -07:00
Dan Abramov
10a600854c Fix a simplifer issue
Summary:
This might be wrong, I haven't though about it in depth yet.
Appears to fix https://github.com/facebook/prepack/issues/1930 and https://github.com/facebook/prepack/issues/1830.

Tests pass.
Closes https://github.com/facebook/prepack/pull/1933

Differential Revision: D7954943

Pulled By: gaearon

fbshipit-source-id: e19166cc22efcffbe7c4082d3df5e5c82c9f79e8
2018-05-10 12:09:08 -07:00
Nikolai Tillmann
4b980396c9 Don't serialize changes to property bindings that represent internal slots
Summary:
Release notes: None

This fixes #1856, at least in the sense that Prepack won't silently generate wrong code.
Instead, Prepack will now issue an error indicating that a Prepack limitation was hit.

Adding error-handler regression test.

Also fixed reference to PP1023 (no wiki page) to be PP0023 (matching wiki page) instead.
Closes https://github.com/facebook/prepack/pull/1929

Differential Revision: D7954903

Pulled By: NTillmann

fbshipit-source-id: f9676f33e74ff36067832333a7ee9a26ec77126d
2018-05-10 12:09:01 -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
Herman Venter
8f2e2fe353 Prevent CSE from hoisting Object.assign calls.
Summary:
Release note: none

Resolves issue #1865

Abstract values that are known to result in objects (of unknown identity) should not be eligible for Common Subexpression Elimination (CSE).
Closes https://github.com/facebook/prepack/pull/1925

Differential Revision: D7941893

Pulled By: hermanventer

fbshipit-source-id: 454e26c6d042093b9fbae06d73110202083731b6
2018-05-09 15:49:56 -07:00
Nikolai Tillmann
693250fea2 Adding regression test for #1881
Summary:
Release notes: None

Closes https://github.com/facebook/prepack/pull/1919

Differential Revision: D7936510

Pulled By: NTillmann

fbshipit-source-id: 5165537ff8d3b9800ab3cbdda250d38f13059a2c
2018-05-09 12:12:19 -07:00
Dominic Gannaway
19b2bde1bb Fixes an issue with getOwnPropertyDescriptor
Summary:
Release notes: fixes an issue with getOwnPropertyDescriptor when dealing with a native prototype function

This PR fixes #1285, specifically when using `Object.getOwnPropertyDescriptor` on a native prototype function, we have to resort to returning a temporal abstract as this function isn't available at build time. I also renamed all the tests with typos in them.

cc anilanar
Closes https://github.com/facebook/prepack/pull/1913

Differential Revision: D7935215

Pulled By: trueadm

fbshipit-source-id: d7e33cf8bd73aa2c1156966ad86e9da9fb0404e4
2018-05-09 11:09:05 -07:00
Herman Venter
bfde1606e1 Stop processing statements after program terminating exception
Summary:
Release note: Do not generate code for unreachable global code statements

Resolves issue #1906

If an unconditional throw is encountered, it does not make sense to keep processing top level statements.
Closes https://github.com/facebook/prepack/pull/1908

Differential Revision: D7934963

Pulled By: hermanventer

fbshipit-source-id: d6e6b26d7ad7c54a065e43a74ad1b27959159c7a
2018-05-09 10:50:17 -07:00
Dan Abramov
c4c1593b22 Add a serializer regression test for #1833
Summary:
Regression test.
Closes https://github.com/facebook/prepack/pull/1916

Differential Revision: D7931571

Pulled By: gaearon

fbshipit-source-id: a442ad2cb68c97d731dd8fbe03886562c8dde18c
2018-05-09 09:40:25 -07:00
Nikolai Tillmann
6fe3600e05 Fix various issues in serializer and emitter around target body selection.
Summary:
Release notes: None

This fixes #1821.

Improve tracking of target bodies in Emitter,
which is necessary now that generators can have effects
and one should not attempt to emit into a body
with the wrong effects in place; removed some dubious code there.

It turned out that the exact placement of `Object.freeze` and similar statements
was always a bit fragile; this issue came out after fixing the Emitter, and so
this is made robust by keeping track of the
emission of all other object property mutations, and only emitting the
`Object.freeze` after they are all done.

When visiting modified property bindings, re-visit object in case it was
previously visited from a different scope.

For objects visited (only) in scopes where additional generator effects have been
applied, record additional information for serialization to ensure that these
objects get serialized in their creation scopes, so that the initial values
of the object properties are not polluted by the additional generator effects
of some nested scope.

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

Differential Revision: D7928970

Pulled By: NTillmann

fbshipit-source-id: e8587be393fb078cc503718932057d7b10d0df72
2018-05-09 07:13:49 -07:00
Herman Venter
8008859a43 Do not apply the effects of JoinedAbruptCompletions.
Summary:
Release note: Fix problems with duplicated and missing statements

Resolves issue: #1842

Code duplication happened because the joined effects of two abrupt completions were applied first in aggregate and then again individually.

While debugging through this, I found it much simpler to understand Generator.fromEffects when applied to an Effects that has not been joined, so now things are closer to what they were before I started trying to hack past issues. The main difference is that a fully joined up set of effects is applied before serializing the result from Generator.fromEffects.

All of this caused an invariant to fail during a test. The invariant is complicated, fails in other new scenarios and is being reworked by Nikolai, so I've removed it for now in order to get these fixes in so that we are all on the same page again.
Closes https://github.com/facebook/prepack/pull/1903

Differential Revision: D7920610

Pulled By: hermanventer

fbshipit-source-id: 89b6ac9f1b8df776657c3a93550fdd3eb2ae4cd7
2018-05-09 03:18:20 -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
Nikolai Tillmann
3371257f29 Properly serialize object of modified object property
Summary:
Release notes: None

This fixes #1857.

The implementation to serialize modified object properties
didn't actually kick off serialization of the modified object.

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

Differential Revision: D7889917

Pulled By: NTillmann

fbshipit-source-id: c665c685a4d2f3b0a06238ea5b04c40c294bb45a
2018-05-05 17:38:05 -07:00
Dan Abramov
e72989cad6 Add a serializer regression test for #1832
Summary:
Adds a regression test for https://github.com/facebook/prepack/issues/1832.

It was fixed in https://github.com/facebook/prepack/pull/1863 but the regression tests in it didn't cover against the specific invariant I was bumping into.

I checked this test fails before the fix.
Closes https://github.com/facebook/prepack/pull/1880

Reviewed By: trueadm

Differential Revision: D7889850

Pulled By: gaearon

fbshipit-source-id: de8b534466b6a28dd3b87f9834344aeda248c29b
2018-05-05 17:05:22 -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
Herman Venter
1570474ed6 Avoid duplicating generators
Summary:
Release note: none

When joining PossiblyNormalCompletions/JoinedAbruptCompletions while promoting particular kinds of completions (such as return completions), do not compose normal effects since that has already happened.

Thanks to Sapan for finding the issue, making a nice test case and identifying the code that is at fault.

This PR supersedes #1872.
Closes https://github.com/facebook/prepack/pull/1875

Reviewed By: trueadm

Differential Revision: D7888926

Pulled By: hermanventer

fbshipit-source-id: 58071b80ce68e89e5a38c0b7b5a2061c5539a304
2018-05-05 06:22:18 -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
697073b72a Deal with joins of joins when promoting
Summary:
Release note: none

While debugging various issues with generators, I noticed that joinEffectsAndPromoteNested does not quite live up to its advertising because it does not handle all the permutations of results that could contain abrupt completions of the given type.

Fixed this and added test cases. The tree manipulations are quite subtle. I went to some trouble to verify that they are correct, using diagrams, but did not want to put the diagrams in the code, so the reading may be a bit tough.
Closes https://github.com/facebook/prepack/pull/1873

Differential Revision: D7886038

Pulled By: hermanventer

fbshipit-source-id: df874ca5fad771932490428d54ff22b022fec74c
2018-05-04 17:24:08 -07:00
Sapan Bhatia
9fe584fe9f Fix while and for loops with unlabeled breaks
Summary:
BreakCompletions that were not joined previously fall through joinAllLoops. This change converts such cases to NormalCompletions. Without this change, prepacking fails with an invariant failure.
Closes https://github.com/facebook/prepack/pull/1863

Differential Revision: D7876263

Pulled By: sb98052

fbshipit-source-id: fed191c1163da412291c6a09674220b6133a99b1
2018-05-04 04:35:30 -07:00
Sapan Bhatia
8ec0b2efaa Set value of joined BreakCompletions
Summary:
Small fix to value of joined BreakCompletions
Closes https://github.com/facebook/prepack/pull/1861

Differential Revision: D7867413

Pulled By: sb98052

fbshipit-source-id: 94ff51ae0225b8381a79d9fd53128b18448b65a4
2018-05-03 16:01:33 -07:00
Herman Venter
4af05bd908 Deal with possibly normal completions from joined switch
Summary:
Release note: Support switch statements where the switch value is abstract and one or more cases throw

Resolves #1838

When only some of the cases in a switch statement throws, the join results in a possibly normal completion and this has to get composed with the saved completion.

The test case also revealed that the join was happening in the wrong order, so that is fixed as well.
Closes https://github.com/facebook/prepack/pull/1844

Differential Revision: D7861034

Pulled By: hermanventer

fbshipit-source-id: f4a8614e1f8769f942018345e2e1024d8013cf67
2018-05-03 11:51:00 -07:00
Herman Venter
838c26d7a0 Fix _WrapAbstractInObject to deal with mixed primitive types
Summary:
Release note: Fixed bug with implicitly converting unknown values to Object

Resolves #1845

Joined values can be of type PrimitiveValue, so the invariant in the default case of the switch in _WrapAbstractInObject is actually not true.

Added handling for this case, throwing an error if the joined value might be null, undefined or missing and converting it lazily to Object otherwise.
Closes https://github.com/facebook/prepack/pull/1849

Differential Revision: D7853117

Pulled By: hermanventer

fbshipit-source-id: eb8e8d85c13f9eee4320badb2209c5581f27ef0c
2018-05-02 18:35:51 -07:00
Sebastian Markbage
71248cd967 Follow up to UpdateExpression
Summary:
Follow up to #1839

It's not safe to mutate an expression in a build function. Those needs to be emitted as statements.

We don't have to deal with the assignment part of it though. We can just calculate the new value and deal with the fact that ToNumber might throw or mutate.

The new value we can just pass to PutValue which takes care of the rest.
Closes https://github.com/facebook/prepack/pull/1847

Differential Revision: D7853622

Pulled By: sebmarkbage

fbshipit-source-id: 1e370c2961048f5ce22becb7385a84b92ecc7045
2018-05-02 17:04:06 -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
Herman Venter
72994a6851 Generalize temporal unknown property assignments
Summary:
Release note: Support multiple assignments to unknown properties in optimized functions

Issue #1818.

The code in #1822 can only deal correctly with a single assignment. This generalizes that code to generate separate assignments for each different (key, value) pair found in the conditional value tree that is used to model a group of assignments to unknown properties of known objects.
Closes https://github.com/facebook/prepack/pull/1828

Differential Revision: D7840880

Pulled By: hermanventer

fbshipit-source-id: 8f2bb12cfd5246dc13d5a360ff9bb16a9326dd41
2018-05-01 19:24:58 -07:00
Herman Venter
c3a1fd3c46 Special handling for temporal assignments to unknown properties
Summary:
Release note: Support temporal assignment to object properties using unknown property names

Resolves issue: #1818

There was no code for dealing with assignments using unknown property names that showed up in generator entries.
Closes https://github.com/facebook/prepack/pull/1822

Differential Revision: D7833068

Pulled By: hermanventer

fbshipit-source-id: 2c3e8d211bd4770ba736ff9be03a0f4d85adad34
2018-05-01 13:10:49 -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
Nikolai Tillmann
065fa2765b Refine type of PropertyBinding.key
Summary:
Release notes: None

This fixes #1771.

The `PropertyBinding` `key` type used to be just `any`; not sure what the historical story here is,
but the visitor was unaware that this in fact could be an `AbstractValue` as well as a `string`.
This meant that some keys might not get visited when they should have been.

This refines the key type and accounts for the different possible types in all referencing places.
Closes https://github.com/facebook/prepack/pull/1816

Differential Revision: D7827049

Pulled By: NTillmann

fbshipit-source-id: 88fa2e036d1d4393d025af38954e309f6632a839
2018-04-30 22:10:52 -07:00
Herman Venter
ec1b83eb29 Do not simplify c ? NaN : y to y if the path implies (c ? NaN : y) !== NaN.
Summary:
Release note: Fixes simplification bug involving comparisons with NaN

Issue: #1790

Simplification operations that reduce conditional expressions based on inequalities, must guard agains comparisons with NaN.
Closes https://github.com/facebook/prepack/pull/1815

Differential Revision: D7824224

Pulled By: hermanventer

fbshipit-source-id: 34249c8597bb44421742919737f74ca93e2035e5
2018-04-30 18:10:42 -07:00
Herman Venter
6ee4ca00d4 Always apply effects before combining their results with saved_result
Summary:
Release note: Resolves issues with outer declarations moving into nested scopes

Issue: #1808

The fix identified in #1805, needs to be applied in a number of other contexts as well.
Closes https://github.com/facebook/prepack/pull/1813

Differential Revision: D7821306

Pulled By: hermanventer

fbshipit-source-id: dd08198f5d031c2e368bf5da179c2a11ac0f3b3a
2018-04-30 15:40:17 -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
Nikolai Tillmann
acfae3870c Fixing mutations of objects-from-outer-scope in optimized functions.
Summary:
Release notes: None

This fixes #1789.

The visitor already computed the right scopes for all objects,
which the serializer then used to figure out in which code block
to emit an object.
However, the serializer didn't take into account that the wrong
effects might be applied when serializing values in a simple
recursive manner, finding an object from an outer scope while
serializing an optimized function.
To fix this, (re-)introduce an additional roots set which is used
to ensure that all objects belonging to an outer scope get serialized
before we enter an additional function where effects might get applied.

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

Differential Revision: D7814388

Pulled By: NTillmann

fbshipit-source-id: 5709fcd676b9b86dd66b2952155039d09d873a70
2018-04-30 09:55:19 -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
Herman Venter
30876d5bec Special case switch over abstract value with known values domain
Summary:
Release note: none

Addresses issue: #1763

If the abstract selector value of a switch statement has a known values domain and ranges over a small set of values, we can generate better code by not having to join up all the case blocks in the switch.
Closes https://github.com/facebook/prepack/pull/1786

Differential Revision: D7792997

Pulled By: hermanventer

fbshipit-source-id: 147f52ad666f2617a8e16c3d7363341742adf2f9
2018-04-27 11:46:13 -07:00
Herman Venter
a2a5d60fc2 Keep generator entries that do not come from joins
Summary:
Release note: none

Fixes issue: #1766

Generators that result from joining two blocks of code have lots of entries that are the joins of the generators of the individual blocks. When generating code for optimized functions, these entries need to get ignored since they will be visited while recursing through the top level result. That much was achieved with the PR #1758.

That turned out to be too simplistic since joined generator entries can get appended into generators with existing entries. This PR restores visiting generators from effects with joined results, but purges them of entries that resulted from the join.

This is somewhat brittle and we need to revisit the entire generator design at some point, but this PR gets us unblocked and does seem to make things strictly better.
Closes https://github.com/facebook/prepack/pull/1795

Differential Revision: D7787380

Pulled By: hermanventer

fbshipit-source-id: 23e8924282cfdabf77969ff716ac936c12daa6ad
2018-04-26 23:36:53 -07:00
Nikolai Tillmann
922ac349e9 Don't emit object property modifications to dead objects.
Summary:
Release notes: None

This fixes #1772.

When an optimized function modifies properties of objects
created outside of its scope, we can omit such property modifications
if the modified object is not used.
This nicely fits in with the fixed point model of the visitor.
(The objects involved in object property modification used to complete bypass the whole visiting process, resulting in the crash.)
Note that as a positive side effect certain double-mutation errors won't be issued to the user.

Added simple regression test.

Manually verified that this also makes the larger React test mentioned in the issue pass.

Also fixed ordering ordering of effects applications when processing queue in residual heap visitor. This bug existed for a while, but was only brought out by the existing serializer tests after the more aggressive queueing of modified object property binding visitng.
Closes https://github.com/facebook/prepack/pull/1793

Differential Revision: D7784644

Pulled By: NTillmann

fbshipit-source-id: 3dd21cc89275a30c5312f7bdd94e7d0364d02959
2018-04-26 22:41:06 -07:00
Nikolai Tillmann
94245b1d14 Fixing equals
Summary:
Fixing equals() on Values

Release notes: None

I found the following bugs in equals():
- For numbers, it didn't take into account NaN.
- For symbols, it was too optimistic.
And for objects, it was overly complicated.

Adding regression test for symbols. Could produce a regression test for numbers, but file a related issue for NaN values.
Closes https://github.com/facebook/prepack/pull/1791

Differential Revision: D7784665

Pulled By: NTillmann

fbshipit-source-id: 96bdcce6c771c8549dc52cd73c646d0e15b5b9b0
2018-04-26 22:41:06 -07:00
Herman Venter
d2446b8de0 Promote empty to undefined for optimized function return values
Summary:
Release note: none

EmptyValue is a signal that the property that (might) have the value could in fact not actually be there. This matters when constructing objects at runtime, since code has to be emitted to deal with the case where the property will not be created at all, due to a runtime switch.

On the other hand, when the value of a missing property is *used*, it should be the undefined value. For that scenario, there is a promoteEmptyToUndefined on Value and this should be called before serializing empty values that are actually used.

This was not done for values returned from optimized functions. This PR plugs that hole.
Closes https://github.com/facebook/prepack/pull/1787

Differential Revision: D7776331

Pulled By: hermanventer

fbshipit-source-id: ebf8f5335e8ed3f6c557e00f3c88b08ccbd9c14d
2018-04-26 14:22:20 -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
Herman Venter
de52327593 Handle abstract conditional break inside definite for loop
Summary:
Release note: Allow break/continue to be guarded by abstract conditions inside loops

This addresses the first example in issue: #1764

Loops represent join points for break and continue completions. They need to be handled much like the return completions that join at function end. The main difficulty is that break and continue can specify a target. For now, we punt on that and give a compile time error.
Closes https://github.com/facebook/prepack/pull/1778

Differential Revision: D7762824

Pulled By: hermanventer

fbshipit-source-id: d8d3699277b7bb20817a27ecc24f3c503904fc74
2018-04-26 01:58:46 -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
Herman Venter
64ee2744ee Capture prefix effects when composing pnc
Summary:
Release note: none

When composing a newly constructed PossiblyNormalCompletion with saved one, the resulting completion needs to capture the effects that happened on the normal branch, in between the saved fork point and the fork point of the newly constructed completion, because these effects also apply to the abrupt part of the new completion.

When joining up such a composed completion, the effects need to be applied (and later reversed), otherwise the nested joins might capture values as they were before the first fork, rather than as there were at the time of the nested fork.
Closes https://github.com/facebook/prepack/pull/1769

Differential Revision: D7746284

Pulled By: hermanventer

fbshipit-source-id: d2396f29f93c676e330ac6460f5ac9e638329528
2018-04-24 11:57:49 -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
Nikolai Tillmann
dee52a104a Fixes mismatch between visitor and serializer.
Summary:
Release notes: None

The serializer used simply invoke the serialization
machinery for the special empty value when it was
trying to generate code for a possibly-deleted property.
However, there was no matching visiting of the special empty value.

This fixes issue #1747.

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

Differential Revision: D7672464

Pulled By: NTillmann

fbshipit-source-id: 60b2e4eb4246abb61d2361b8ef88d293de021ef5
2018-04-19 12:32:49 -07:00
Herman Venter
2b1bf611db Do not emit joined generators into optimized function bodies
Summary:
Release note: none

Joining effects results in joined generators that contain all of the I/O operations of the argument effects, but does not change the arguments.

Normally, this does not matter because only the joined generator is used. In the case of an optimized function, however, the generator tree is traversed via the effects tree and this resulted in duplicate I/O operations.

To fix this, the tree walk now ignores joined generators. Also included in this PR, some fixes to make sure that only the (joined) effects resulting from _createAdditionalEffects are used, and not the effects that went into it.
Closes https://github.com/facebook/prepack/pull/1758

Differential Revision: D7687328

Pulled By: hermanventer

fbshipit-source-id: c3a333369bc403bed5f986e5d9d59cc56ab62ced
2018-04-19 10:30:32 -07:00