Commit Graph

246 Commits

Author SHA1 Message Date
Jeffrey Tan
084e51ff17 Fix additional function mutable binding function scope
Summary:
Release Note: none

Fix #1238
The behavior of the bug is that, get_scope_binding() helper function is generated in wrong scope: global scope instead of additional function scope.
It happens because there are two scopes referencing it, additional function itself and its parent generator scope. The second one is problematic because "obj" is not referenced in parent generator scope. We should visitPropertiesAndBindings only from additional function scope itself instead of parent generator scope.

[The changes in react compiler]: with above change, all the hoistable react elements will be in additional function's parent generator scope so align the change in the react/hoisting.js file.
Closes https://github.com/facebook/prepack/pull/1291

Differential Revision: D6643868

Pulled By: yinghuitan

fbshipit-source-id: c14ab00792e530bdd592052d012434957defd01f
2017-12-28 16:09:27 -08:00
Herman Venter
cfdd9df527 Provide for intrinsic abstract arrays
Summary:
Release note: none

Add a do-while test where the termination condition involves the length of an abstract array.

Since we did not have abstract arrays, this is mainly about adding those. Also, there was no support for getting a property from an abstract object that is not template based, so added that too. Also added a special case to return an abstract value of type NumberValue if the abstract object is known to be an array and the property name is known to be "length".

Finally, fixed a typing error in createAbstractFunction. It turns out, ahem, that Flow was not confused at all, just obtused.
Closes https://github.com/facebook/prepack/pull/1297

Differential Revision: D6633451

Pulled By: hermanventer

fbshipit-source-id: 23302999002ca35d3141a1666afd76c3b9208de7
2017-12-23 11:09:17 -08:00
Herman Venter
83508ef1ee Handle computed property names using loop variables
Summary:
Initial bit of support for dealing with abstract loops where the loop body contains assignments to properties with computed names involving loop controlled variables.
Closes https://github.com/facebook/prepack/pull/1286

Differential Revision: D6628885

Pulled By: hermanventer

fbshipit-source-id: 960fa469e3c18e55e5447ac441235a80df2b1629
2017-12-22 13:22:54 -08:00
Jeffrey Tan
e61d29fb25 Enhance TypeDomain for oprands with unknown type in binary operation
Summary:
Release Note: Enhance TypeDomain for operands with unknown type in binary operation

Fix #999
Closes https://github.com/facebook/prepack/pull/1292

Reviewed By: hermanventer

Differential Revision: D6625200

Pulled By: yinghuitan

fbshipit-source-id: ed774aed079541e394a8fea4094fbac79e64bcc6
2017-12-21 17:40:01 -08:00
Herman Venter
34b88f4b49 Deal with explicit property deletions inside abstract loops
Summary:
Release note: none

Add some test cases that have loops that delete properties in some iterations but not others.
Deal with it by explicitly testing for __empty values.

Issue #1174
Closes https://github.com/facebook/prepack/pull/1281

Differential Revision: D6622901

Pulled By: hermanventer

fbshipit-source-id: c41a5426b062f08ebeb0e6c2f26ad690d6c43ec8
2017-12-21 14:24:10 -08:00
Chris Blappert
b66cadde91 Make additional function capture more precise
Summary:
This PR attempts to resolve issue #1140 #1093 making additional functions capture precisely the values the rewritten additional function will need.

This is accomplished by visiting the additional function's effects when we encounter a `visitValueFunction` corresponding to that additional function.

All values that need to be serialized in the parent scope of the additional function:
1. Object/Function captures that are
a. from the additional function or nested functions
b. not in CreatedObjects (i.e. created in a parent scope)
2. additional function's captures that will be used by rewritten function
These are re-visited from the function's parent scope to make sure that we record the scopes for the bindings correctly.

`reVisitSet` ensures that Objects/Functions that need to be in a parent scope get placed in the correct parent scope by appending them to the common generator (where `_getTarget` would emit them). The other reason for this is that while serializing additional functions, they don't have access to previous generators/bodies.

Other changes:
- `test-runner.js` now tests simpleClosures option. This makes test-serializer take a long time so
- there is now a `--fast` option as well that runs each test only once.
- `test-runner.js` also has more error output giving actual stacktraces.
- added tests
- moved specialized binding functions into `visitBinding`
- add `react-mocks` compatibility option to CLI to be able to debug `test-react` with cli
Closes https://github.com/facebook/prepack/pull/1279

Differential Revision: D6617232

Pulled By: cblappert

fbshipit-source-id: 6211262561ffc954be8b1346ad7737f4360a2416
2017-12-20 17:55:28 -08:00
Sebastian Markbage
6b926d2aff Allow Side-effectful Abstract Functions in Pure Additional Functions
Summary:
TL;DR this tracks any reachable object or binding that a side-effectful function could mutate as having an unknown value after that call.

In the React compiler we see a lot of examples like this:

```js
return <div>{obj.unknown.toString()}</div>
```

Where we're calling an abstract function, or even calling a generic abstract value due to unknown being abstract.

This is an example that we currently use Flow types for. Flow lets us know that this is a number and therefore toString is known to be pure. However, fully plugging in Flow will be limiting and hard. Flow is also overkill for our use case. We still can't compile away the function call since we'll have to leave a residual call to toString anyway.

Now we could assume that all calls are pure, however, we also see a lot of patterns like this:

```js
var children = [];
obj.items.forEach(item => children.push(<Item item={item} />);
var data = knownFunction(obj.data);
return <div><Foo>{children}</Foo><Bar data={data} /></div>;
```

In this case the children array gets locally mutated. If we knew the `forEach` function here was an array (as opposed to some other `forEach` side-effectful method), then we know what it could do. Even if we knew this would deal with a loop over an abstract bound. But this assumes that we even know this is an array.

It would be sufficient for us to just leave this call in an treat the children as abstract. Even with best effort, that is more or less what's going to happen anyway.

We don't want to completely bail out on the whole function because we want to know the fact that this always returns a `<div>` with a `<Foo />` and a `<Bar />` in it so that we can continue with those. We can also inline the knownFunction call.

Once we're inside a "pure function" such as a React component or additional function, there can be mutations.

Such a function can only mutate newly created objects and bindings, and read immutable data. That's not technically enforced but that's what the whole principle builds on.

This means that any abstract call to a function that was passed in, or lives in global scope, cannot have side-effects on anything except what was passed in as an argument (or `this`).

This PR introducing a new concept of tainting objects and bindings as abstract values after they've been passed to an impure function call.

After they have been tainted all mutations to them are tracked through a generator.

Any subsequent operations on these objects or bindings behave like access to abstract values.

When we enter evaluation of a "pure function" we track that scope and track all newly created objects within it as "impure".

When an abstract function call happens, I visit all arguments that are in the impure list recursively. I stop when I hit an object not on the list, since that can't be mutated.

For objects, I mark them as "tainted", reset all properties and make it partial. That way all subsequent property accesses are unknown. The abstract function call could've done anything with it, including deleting all properties.

Currently I always serialize tainted objects as empty, but I set all the properties to what they were at the first call.

Once an object is tainted, any subsequent operations on it emit to the generator.

If a function is passed in, I also taint all the _newly created_ bindings that are reachable from that closure.

Reads on a tainted binding return a new derived abstract value that replays a read of that binding. To do that I had to add a way to expand `buildNode` to be able to accept `Binding` as an argument. Not just `Value`. That way the `Referentializer` can decide what name the binding needs to serialize as.

I currently left out error handling. Normally that doesn't matter, because if the function call throws, it will bubble up to the pure function call and act like it would've anyway.

Errors only matters if there is a `try`/`catch` anywhere between the abstract call and the pure function call. That should be solvable but even this case is so rare that it is probably fine to fatal in that case.

Once we have function calls in place, we can later follow up by unlocking other operations that currently only fatals because we don't know if they will invoke side-effectful functions.
Closes https://github.com/facebook/prepack/pull/1142

Differential Revision: D6606775

Pulled By: sebmarkbage

fbshipit-source-id: 3305a58ad7b311d222a4b3ce8437056497154edf
2017-12-19 19:09:08 -08:00
Chris Blappert
f4c46000e2 Clean lexically scoped values from ModifiedBindings
Summary:
hermanventer changed the interpreter such that when `popContext` was run, the corresponding `var` bindings from the popped scope were removed. This PR extends that functionality to `LexicalEnvironment`s so that `let` bindings are also removed when the Lexical scope is removed.

This is necessary for #1093 / #1140.
Closes https://github.com/facebook/prepack/pull/1217

Differential Revision: D6594205

Pulled By: cblappert

fbshipit-source-id: 85440e5b591bba6118724140e0e0764f573fbd00
2017-12-19 11:11:00 -08:00
Herman Venter
92979e2c91 Deal with loops where early iterations do not assign to a property
Summary:
Release note: none

This is the first among a number of step to deal with the gnarly edge cases that arise because a property can be absent (empty) rather than just undefined.
Closes https://github.com/facebook/prepack/pull/1278

Differential Revision: D6596190

Pulled By: hermanventer

fbshipit-source-id: f18f181e617a50e1bb39015378330dee14d71815
2017-12-19 11:11:00 -08:00
Manas
104fd40103 Support implicit abstract conversion during binary operations
Summary:
Addresses #1109
Closes https://github.com/facebook/prepack/pull/1258

Differential Revision: D6596652

Pulled By: hermanventer

fbshipit-source-id: cf0cf18c40a67e77f755e80e323544e3152c235d
2017-12-18 15:35:43 -08:00
Baptiste Manson
bad3ec4720 fix #1239 - Command-line based syntax errors now print location
Summary:
Hi all!

I took the path to implement a custom errorHandler, to be more aligned with the rest of the code, but it may be a mistake.

I reached that point.
```bash
echo "(){}" | yarn prepack
yarn prepack v0.27.5
$ node lib/prepack-cli.js
Unexpected token (1:1) found in stdin
Error: A fatal error occurred while prepacking.
+ (full stack trace)
error Command failed with exit code 1.
```

and when srcmapIn is given but not existing:
```bash
 echo "(){}" | yarn prepack -- --srcmapIn notExisting
yarn prepack v0.27.5
$ node lib/prepack-cli.js "--srcmapIn" "notExisting"
No sourcemap found at notExisting.
Unexpected token (1:1) found in stdin
+ (stack trace)
```
Finally when using files with syntax error:
```bash
yarn prepack ../notepad/test.js
yarn prepack v0.27.5
$ node lib/prepack-cli.js "../notepad/test.js"
Unexpected token (1:3) found in input file ../notepad/test.js
+ (stack trace)
```
Closes https://github.com/facebook/prepack/pull/1272

Differential Revision: D6595324

Pulled By: hermanventer

fbshipit-source-id: 6f73a15db5710585ffc9579f4487217a98f921f5
2017-12-18 13:56:26 -08:00
Dominic Gannaway
4e6c988723 Hoist and re-use React Elements when it's safe to do so
Summary:
Release note: none

This PR aims to do a few optimizations in terms of how JSX/React Elements are handled.

I've introduced a `ReactElementSet` class that aims to handle matching similar React Element/JSX structures by deeply iterating through the various properties on a JSX element. It uses a linked hash map, with the keys being the reference to the specific internal Prepack value. It handles objects, arrays, functions and React element structures.

These optimizations only happen on evaluated component trees.

```jsx
// before:
function MyComponent(props) {
  return <div><span>Hello world</span><span>Hello world</span></div>
}

// after:
function MyComponent(props) {
  var _0 = <span>Hello world</span>
  var _1 = <div>{_0}{_0}</div>
  return _1;
}
```

```jsx
// before:
function OtherComponent() {
  // ...
}

function MyComponent(props) {
  return <div><OtherComponent data={{a: 1, b: 2}} /></div>
}

// after
function OtherComponent() {
  // ...
}

function MyComponent(props) {
  _1 === void 0 && $f_0();
  return _1
}

function $f_0() {
  _1 = <div><OtherComponent data={{a: 1, b: 2}} /></div>
}
var _1;
```
Closes https://github.com/facebook/prepack/pull/1196

Differential Revision: D6578563

Pulled By: trueadm

fbshipit-source-id: 2f617fd80d4540228fcb60403cb97e672763876b
2017-12-15 08:08:19 -08:00
Herman Venter
45d19dd152 Assign simple properties inside loops
Summary:
Release note: Basic support for do while loops with abstract bounds. Issue #1229

Take properties into account when doing fix point computation. Use property paths rather than phi nodes. Simplify code for local variables as well.
Closes https://github.com/facebook/prepack/pull/1255

Differential Revision: D6576293

Pulled By: hermanventer

fbshipit-source-id: 9e19704cbf5c8cbcc937bd99ec32af9ffe577ebf
2017-12-14 19:38:55 -08:00
Chris Blappert
78deba64a1 Fix ordering of binding mutation in additional functions
Summary:
Release Notes: none

Addresses issue #1244. Now we will put modifications to bindings just before the return statement of the additional function.
Also contains some minor refactors.
Closes https://github.com/facebook/prepack/pull/1251

Differential Revision: D6568331

Pulled By: cblappert

fbshipit-source-id: ea3ae2a783355175f0f23f82bce6543ac535b214
2017-12-14 10:24:58 -08:00
Simon Jensen
989210d5b8 When conditionally returning, add condition to non returning path
Summary:
Release note: Use conditional returns to refine the path condition. Fixes #1182

When one branch of a conditional is an abrupt completion add the join condition to the path condition. The previous path condition is stored in the saved completion and restored at join point.
Closes https://github.com/facebook/prepack/pull/1212

Reviewed By: hermanventer

Differential Revision: D6562943

Pulled By: simonhj

fbshipit-source-id: fcf53a7c54118628bd3f62e5010f4c1046fd1145
2017-12-13 17:09:45 -08:00
Herman Venter
5e86f790aa Do not conflate prior saved completion with one from call.
Summary:
Release note: Fix bug #1262

The saved completion that is present before a function call should not be incorporated into the saved completion that is created inside the call, until after return completions have been appropriately joined and applied.
Closes https://github.com/facebook/prepack/pull/1263

Differential Revision: D6560937

Pulled By: hermanventer

fbshipit-source-id: 76e8d67f0ad2227dec9cf54f5f035a34f1941be3
2017-12-13 15:10:47 -08:00
Nikolai Tillmann
8d4e36092f Prepend additional functions prelude *after* splicing in function declarations
Summary:
Release notes: none

This addresses the --simpleClosures case mentioned in #1238 (but not the other case where we delay closure scope creation).

Prepend additional functions prelude *after* splicing in function declarations,
otherwise the ordering of the insertions is messed up.
Adding regression test.
Closes https://github.com/facebook/prepack/pull/1241

Differential Revision: D6546269

Pulled By: NTillmann

fbshipit-source-id: eb12c5bbba1b542c4e69599e5abf961359d41652
2017-12-12 11:39:01 -08:00
Manas
8ece9d1b3e Check if intrinsic abstract values have unique names
Summary:
Fix for #1155
Closes https://github.com/facebook/prepack/pull/1197

Differential Revision: D6546346

Pulled By: hermanventer

fbshipit-source-id: 7c24e1ce4ebf121a6d50176e7dc124d83f7cdad4
2017-12-12 11:39:00 -08:00
Herman Venter
a0ece2f8b4 Compute a fixed point for do-while
Summary:
Release note: Handle do-while loops with abstract bounds, for loop bodies only involving locals.

Issue: #1174

This adds a simple fixed point computation for do-while loops only. Currently only loops that updated only local variables and that have no abrupt exits are supported.

This is deliberately as minimal as possible to make review easier. Given the complexity of this feature, thoughtful review would be great.
Closes https://github.com/facebook/prepack/pull/1229

Differential Revision: D6546405

Pulled By: hermanventer

fbshipit-source-id: 205c336a83c17d03344941b13f0a5c6af7989131
2017-12-12 11:24:29 -08:00
Lukas Koebis
1130390174 Fix: Repeated argument identifiers with inlined expressions.
Summary:
PrePack generates duplicate argument names when inlining expressions. Take for instance the test in test/serializer/basic/CapturedScope.js. PrePacked with --inlineExpressions it generates several functions like

```
var $_1 = function (c, __scope_2, __scope_2) {
    var __captured__scope_2 = __scope_1(__scope_2);

    var __captured__scope_2 = __scope_1(__scope_2);

    __captured__scope_2[1]++;
    __captured__scope_2[2]++;
    return c();
  };
```
Closes https://github.com/facebook/prepack/pull/1218

Reviewed By: hermanventer

Differential Revision: D6536751

Pulled By: lukas1994

fbshipit-source-id: 8752964d7c099476a4cda3d42996c0aa77cbb5b9
2017-12-11 13:24:38 -08:00
Christopher Blappert
219a4e009b Fix serialization of circular function captures
Summary:
Fixes #1222 by refusing to emit `.bind` calls when the arguments of the `.bind` would be identifiers for functions that have been generated by the ResidualFunctions code (because we can't guarantee that the ordering will be correct).
Closes https://github.com/facebook/prepack/pull/1227

Differential Revision: D6527609

Pulled By: cblappert

fbshipit-source-id: 55953c70eca5f230e5a9e371ac07219e7cafaa61
2017-12-08 18:24:01 -08:00
Nikolai Tillmann
f539656800 Fixing ordering issue with simple-closures.
Summary:
Release notes: none
Towards closing #1226.
Add regression test case.

Note that simple-closures doesn't work together with delay-initializations,
so delay-initializations now gets silently disabled when needed.
Closes https://github.com/facebook/prepack/pull/1237

Differential Revision: D6526798

Pulled By: NTillmann

fbshipit-source-id: 1b21961aaadd98af9503846b065689db38bd5302
2017-12-08 17:26:16 -08:00
Nikolai Tillmann
b4a30df0f0 Adding option --simpleClosures to eagerly allocate space for captured variables.
Summary:
Release notes: Adding option --simpleClosures to eagerly allocate space for captured variables.

This addresses #1226.

Adding option --simpleClosures, and brought back code that avoids delaying closure creation.
Adding test case.

From here, we could tweak the logic that triggers this behavior.
Closes https://github.com/facebook/prepack/pull/1228

Differential Revision: D6516797

Pulled By: NTillmann

fbshipit-source-id: 9c556036f8dd64c4c6004a436c3a391ca428eda9
2017-12-07 18:26:53 -08:00
Manas
43223d2d5d Adapt evaluators to deal with abstract conversion values
Summary:
Attempts fix for #1109 Awaiting feedback for the tests that have been written.
Closes https://github.com/facebook/prepack/pull/1211

Differential Revision: D6498825

Pulled By: hermanventer

fbshipit-source-id: 6bc6def013890561c70b77db6ba582902d677bcf
2017-12-06 11:09:51 -08:00
Dominic Gannaway
f3355c91ca Fold simple class components
Summary:
Release note: Adds support for folding simple React class components

This PR adds the concept of "simple" class components. A "simple" class component is defined as:
- having only a "render" method or many method, i.e. `render()`, `_renderHeader()`, `_renderFooter()`
- having no lifecycle events
- having no state
- having no instance variables

The only things a class component should be able to access on "this" are:
- `this.props`
- `this.context`
- `this._someRenderMethodX()` etc

It does this by first attempting to evaluate any class component with the heuristics as if it were a simple class component. If that throws an error (entirely expected for most class components), it catches the error and falls back to trying to use the "complex" class component route for evaluation instead.

Furthermore, I've added "transforms". This allows post-transforms of the serialized AST for additional functions. The simple class component adds a transform to convert AST nodes of `this.props` to `props` and `this.context` to `context` respectfully – whilst adding arguments to the function; something that is necessary to convert simple class component render methods to functional components.

This PR also adds logic to squash simple class components into functional components at the root (as simple class components are easily convertible to functional components).
Closes https://github.com/facebook/prepack/pull/1204

Differential Revision: D6485508

Pulled By: trueadm

fbshipit-source-id: 06ebeebad5d23c0677a0e3f0cb8dd23c45735429
2017-12-05 08:24:12 -08:00
Herman Venter
bd0d78606d Add !!x => x rule to implication logic.
Summary:
Release note: Add !!x => x rule to implication logic.

Found such a case in the wild.
Closes https://github.com/facebook/prepack/pull/1210

Reviewed By: cblappert

Differential Revision: D6461079

Pulled By: hermanventer

fbshipit-source-id: eed71b37bd816ddf63c84587ae4ebef1296fb2e8
2017-12-01 14:10:31 -08:00
Herman Venter
9f76bae360 Do not let thrown objects escape from delayed modules
Summary:
The logic for delaying modules that fail to prepack did the wrong thing with modules that always throw, by leaking the exception object while backing out the effects of the require call.

To keep things simple all modules that end abruptly are now delayed (when the option is specified) and the exception is discarded.

Eventually, we should just get rid of the delay logic, but for now it seems like useful backup. Feel free, however, to insist that we get rid of it right away.
Closes https://github.com/facebook/prepack/pull/1203

Differential Revision: D6442540

Pulled By: hermanventer

fbshipit-source-id: e3a609af8c37cbe4ac9a8e96fb5c1950c886b435
2017-11-29 16:55:25 -08:00
Jeffrey Tan
e03c61c29f Preserve residual funciton original ordering
Summary:
Release Note: preserve residual functions' original source ordering.

We serialize the residual functions in random order(based on the visitor's discovery of residual function order) which may result in very bad code locality in real world app.
Add the feature to preserve residual functions' original source ordering.

Note:
1. I did not make an option for this feature because I think it should do this by default.
2. To gain better perf, we may introduce some profiler guided optimization in future.
Closes https://github.com/facebook/prepack/pull/1163

Differential Revision: D6437299

Pulled By: yinghuitan

fbshipit-source-id: 9c0a93a10862b0d8c96bfccb38238c497e4012e7
2017-11-29 11:08:38 -08:00
Jeffrey Tan
79e0bfcc34 Make Error object use constructor for creation during lazy mode
Summary:
Release Note: Error object will correctly use constructor for creation during lazy mode.

This change fixes a bug that lazy objects feature did not use constructor for creating Error object.
Closes https://github.com/facebook/prepack/pull/1195

Differential Revision: D6420793

Pulled By: yinghuitan

fbshipit-source-id: e1018fd17c6a5ad1e17748b3dc13227e982807d0
2017-11-27 17:09:00 -08:00
Herman Venter
0e460bdb09 Treat first operand of a logical operation as a condition
Summary:
Release note: Partially fixes #1182

When dealing with x || y and x && y where x is an abstract value, we can avoid evaluating x if it is known to be false in the first case and true in the second. When x is being refined with the path condition, it helps to know that the refined result will only be checked for truthiness. Duly add a call to Environment.GetConditionValue to make this happen.
Closes https://github.com/facebook/prepack/pull/1184

Differential Revision: D6420018

Pulled By: hermanventer

fbshipit-source-id: ec45808b0235cda896634c09940a8d20b318eb48
2017-11-27 16:41:38 -08:00
Jeffrey Tan
efa13054b3 Better lazy objects mock test runner support
Summary:
hermanventer suggests use Proxy to mock test-runner hydration for Lazy Objects which is very promising. Here are the improvements using proxy hook mocking:
1. More accurate hydration simulation
2. The 4 failed tests all succeed now.
3. All test mocking support are in test-runner now. No need to serialize ugly test runner comment.
4. I find real bugs after switching to Proxy simulation.

I also changed the test-runner a bit to output full runnable code when test-runner failed. This makes lazy object debugging much easier.
Closes https://github.com/facebook/prepack/pull/1188

Differential Revision: D6402100

Pulled By: yinghuitan

fbshipit-source-id: 1f9ebff99e4b23ff614d8d82fedd112ab8848a75
2017-11-22 17:08:24 -08:00
Herman Venter
583698ea8a Avoid unused property reads on simple objects
Summary:
Release note: Fixes #1179

When a property is written to object, the rather convoluted logic for checking if it is allowed and if a setter is involved end up asking the object three times if it already has such a property.

In the case of a simple partial object, this caused three useless references to the property to appear in the generated code, since the absence of a property is regarded as OK and produces a temporal abstract value that just reads from the object at runtime.

Fixed this by adding a special case when writing to a missing property on a simple partial object.
Closes https://github.com/facebook/prepack/pull/1183

Differential Revision: D6399970

Pulled By: hermanventer

fbshipit-source-id: b964ee399583f3f4f30dc2f1930e06a856952635
2017-11-22 14:53:35 -08:00
Herman Venter
64a15e4003 Improve implies and make rebuildObjectProperty update kind.
Summary:
Fix a few problem that came to light when an environmental model was updated to include an optional boolean flag.
Closes https://github.com/facebook/prepack/pull/1169

Differential Revision: D6363050

Pulled By: hermanventer

fbshipit-source-id: 6b92f76045c759e4ae02507e41c4024af937dafc
2017-11-17 14:33:31 -08:00
Dominic Gannaway
4569636fe4 Fold functional component trees that have a class component as root
Summary:
Currently, you can only fold functional components. This PR aims to allow functional component folding directly into a class component. Essentially, this is an incremental step to adding full class component folding.
Closes https://github.com/facebook/prepack/pull/1135

Differential Revision: D6347566

Pulled By: trueadm

fbshipit-source-id: 18cfe3b9583334d4e3500004b562adec3fa9ecee
2017-11-16 05:23:48 -08:00
Herman Venter
7ee4d95f1b Avoid generating two references to intrinsics that are in union.
Summary:
Serializing the arguments of an "abstractConcreteUnion" causes the abstract element to be assigned to a temp twice (once as a argument and once as the union). Avoid this by returning the serialized value of the abstract argument as the result of serializing the union.
Closes https://github.com/facebook/prepack/pull/1158

Differential Revision: D6337410

Pulled By: hermanventer

fbshipit-source-id: 6eaaa09de1622da076dbe58d5f2a490cb6f3d45b
2017-11-15 14:49:26 -08:00
Herman Venter
378769d273 Fix hash for intrinsic abstract objects
Summary:
Creating a nameless intrinsic object could result in an abstract value with a useless hash in cases where the location is unknown. Instead, use a unique counter.
Closes https://github.com/facebook/prepack/pull/1156

Differential Revision: D6331059

Pulled By: hermanventer

fbshipit-source-id: efcfa4bb418074d086b3f282d18ba70c307dda97
2017-11-14 17:10:13 -08:00
Herman Venter
25b798ed07 Join properties with get/set
Summary:
Release notes: Provides support for joining properties that have get and set methods. Also now fully support properties that are only defined in one branch of an unknown conditional.

The main thing that happens here is that descriptors that result from joins now track the join condition and the original descriptors, so that the serializer can emit conditional code for defining the entire property, which allows it to also conditionally omit properties altogether.

Issue #1015
Closes https://github.com/facebook/prepack/pull/1116

Differential Revision: D6331039

Pulled By: hermanventer

fbshipit-source-id: 42d635d37b9880398cc4e039f2d59a9a5d03cec0
2017-11-14 17:10:13 -08:00
Jeffrey Tan
08f3922e60 Enable lazy objects mode in test runner
Summary:
Release Note: enable lazy objects mode in test-runner.

Note: I will try hermanventer's suggestion to move all lazy objects creation to prelude and hydrate them after that in future PR for a better way to deal with lazy objects testing issue.

1. Enables lazy objects mode in test runner.
2. For JSON.stringify() and for...in constructs that hydrate lazy objects in global code, I added "force hydrate lazy objects" attribute in the generated code telling test-runner to hydrate the objects immediately
3. Disable lazy objects mode for 3 factorify tests and 4 abstract tests.
4. Skip lazy objects mode for react compiler, additional function tests.
5. Fix a bug which only shows up in lazy objects mode: a) if the target body is non-generator body and delay reason is generator body there is no need to wait for it. b) we should use targetBody instead of this._body in emitter if delayReason is a Value.
Closes https://github.com/facebook/prepack/pull/1147

Differential Revision: D6326474

Pulled By: yinghuitan

fbshipit-source-id: 84fd8d3550ea4685da418224c28247ad330da8bf
2017-11-14 12:14:11 -08:00
Herman Venter
fdc2787c1a Fix invariant failure in serializer
Summary:
For global let bindings, the serializer ignored the CSE value provided by the visitor. This led to an invariant failure when looking up the scope of a value that had been replaced by an equivalent value during CSE analysis in the visitor.
Closes https://github.com/facebook/prepack/pull/1149

Differential Revision: D6325186

Pulled By: hermanventer

fbshipit-source-id: 421d5bfc3f4e0c9ec7730af6ff3a38d4b926bcae
2017-11-14 10:46:40 -08:00
Dominic Gannaway
03750d1b3b Removes un-needed React JSX key handling
Summary:
After adding some tests, it turns out that logic to apply keys to arrays was un-needed. This was because, after running the same code through React, the same errors occur when keys are omitted from arrays. We don't need to do any clever tricks to add keys, as it might actually break logic on things that don't need them. I've added the relevant tests and removed the key adding logic, which should help us with the de-duping work (https://github.com/facebook/prepack/issues/1150).
Closes https://github.com/facebook/prepack/pull/1151

Differential Revision: D6323878

Pulled By: trueadm

fbshipit-source-id: ec3fa90c48332ef0715e94335c558570040ed81c
2017-11-14 07:38:33 -08:00
Kevin Gibbons
f9bcb4b871 Do not dead-code eliminate do-while in residual fns
Summary:
Followup to #1061; I thought of another case where it was too aggressive.

Do-while loops with always-false conditions can't be replaced by their body because their body might contain a break or continue, which is illegal (or will have different semantics) if the loop becomes a normal block. In principle the body of the loop could be walked to find those, but frankly I doubt it will come up enough to be worth it.
Closes https://github.com/facebook/prepack/pull/1145

Differential Revision: D6303312

Pulled By: hermanventer

fbshipit-source-id: 0d677076fea6f225573a36fbbc9df1a0bebd959a
2017-11-10 16:10:21 -08:00
Dominic Gannaway
c89c9be055 Revert #1107 and enabled test-react on CI
Summary:
Release Notes: none

Reverts https://github.com/facebook/prepack/pull/1107 due to various `RangeError: Maximum call stack size exceeded` errors when running `test-react`. Increasing stack limit doesn't fix the issue. Screenshot attached:

![screen shot 2017-11-10 at 4 01 23 pm](https://user-images.githubusercontent.com/1519870/32666762-6fcfa324-c630-11e7-8a0b-724056f06e78.png)

. Also enables `test-react` on the CI process.
Closes https://github.com/facebook/prepack/pull/1144

Reviewed By: cblappert

Differential Revision: D6298840

Pulled By: trueadm

fbshipit-source-id: 8d2e8088c4aef4ce064c0159cd49bb79e600bc4a
2017-11-10 12:22:14 -08:00
Chris Blappert
f617e9973f Make Additional Function Capture Precise
Summary:
Release Notes: none.

This fixes #1093. At a high level, captures are currently needed by the additional function only if they are modified.

Implementation-wise we tentatively create all bindings with callbacks to visit them and delete them to make sure that after Additional Functions are visited we have a precise set of captures.

Functionality of the PR is fully there but I would like to refactor it in some way because I feel like it can be cleaner.
Closes https://github.com/facebook/prepack/pull/1107

Differential Revision: D6290712

Pulled By: cblappert

fbshipit-source-id: 8b812e28f83c2cb216c01eb52a10f6cb0873ea8d
2017-11-09 15:46:32 -08:00
Dominic Gannaway
810056d1ec Add React functional component folding
Summary:
Release note: Adds experimental React functional component folding optimizations

This PR is stacked upon PRs #1118 and #1117. Thus, those PRs should be merged before this PR is merged to reduce noise in the diff.

This PR adds a new React Reconciler into Prepack's serialization process, so that React components trees can be folded/inlined into a single component at build time. To fold a component tree, it must be explicitly done via `__registerReactComponentRoot(nameOfComponent)`.

This PR only attempts to fold React functional components, not React ES2015 class components (that will come in another PR at a later date). Furthermore, the `props` parameter on a root component must contain Flow type annotations (otherwise we will have no idea what the values might be). Support flow `propTypes` might also be an addition, but not for this PR.

If the reconciler comes across a component that it cannot fold/inline, it will "bail-out" and try and continue the process without that particular component being folded into the tree.

An example of how this all works (input):

```jsx
function App(props: {title: string}) {
  return (
    <div>
      <ChildComponent title={props.title} />
    </div>
  );
}

function ChildComponent(props) {
  return (
    <span>
      <SubChildComponent {...props} />
    </span>
  );
}

function SubChildComponent(props) {
  return <span>{props.title.toString()}</span>
}

__registerReactComponentRoot(App);

global.App = App;
```

Output:
```jsx
(function () {
  "use strict";

  var _$1 = this;

  var _0 = function (props) {
    var _$0 = props.title;
    return <div><span><span>{_$0}</span></span></div>;
  };

  _$1.App = _0;
}).call(this);
```
Closes https://github.com/facebook/prepack/pull/1120

Differential Revision: D6237333

Pulled By: trueadm

fbshipit-source-id: b58c7d8979ca79a766bb2ee2eb01a380d37c3101
2017-11-06 05:07:36 -08:00
Dominic Gannaway
e63daa5585 Add React/Jest testing infrastructure
Summary:
Release note: none

This PR adds the React/Jest testing infrastructure to Prepack and is stacked on the PR https://github.com/facebook/prepack/pull/1117. Thus, that PR should be merged before this PR is merged to reduce noise in the diff.

This will allow us to test various runtime outputs of React 16 when running original source vs Prepacked source to see if there are any issues/differences that might have an impact on applications. The primary reason for this is to track regressions for the component folding PRs that will land in the future.

Please note, this PR does not contain any reconciler changes, thus `__registerReactComponentRoot(App);` has been commented out of tests to ensure they don't prematurely fail. A follow up PR will enable them once the other React functional component folding PRs get landed.

This PR also adds some mock React globals to be used within tests (and maybe to be further integrated into folding at a future point too). The mocks include `React.Component` and `React.cloneElement` for now.

Furthermore, a `utils/json.js` utility file exists to help normalize the results from the React test renderer so that adjacent JSON text nodes get merged, which is something that may exist because of how the reconciler (once the PR lands) handles inlining of child nodes.

The command to run React tests is `yarn test-react`.
Closes https://github.com/facebook/prepack/pull/1118

Reviewed By: cblappert

Differential Revision: D6208263

Pulled By: trueadm

fbshipit-source-id: d54f3b0e1cc3240e1f142d3da08bc279e4153889
2017-11-02 04:40:33 -07:00
Jeffrey Tan
24c363fc8d Fix wait generator body for delay initializations
Summary:
Release Note: Fix wait generator body for delay initializations.
Fix #1106
There are three issues need to be fixed here:
1. _processValue() should only call _emitAfterWaitingForGeneratorBody() for generator body.
2. emitAfterWaiting() needs to handle emitting into non-generator body
3. _serializeAbstractValue() needs to wait for all its own generator body to be available.
Closes https://github.com/facebook/prepack/pull/1113

Differential Revision: D6215017

Pulled By: yinghuitan

fbshipit-source-id: 82461f1152855a2b7cae8e8033374d58ac199e91
2017-11-01 17:23:22 -07:00
Herman Venter
b2455ec197 Introduce an abstract value that is a kind of union.
Summary:
Release note: Introduce model functions for environment properties that may result in optional values.

Rather than special case intrinsic abstract objects, revert to treating them as not null and not undefined. Instead, there is now an abstract value kind "abstractConcreteUnion" which is the union of an abstract value with one or more concrete values. There are also new helper functions: __abstractOrNull, __abstractOrNullOrUndefined and __abstractOrUndefined that can be used to construct such unions.

The serializer need not know anything about these new kind of values, since their build nodes just defer to the build nodes of the single embedded abstract value that must always form part of the union.

The simplifier has been extended to simplify unions into their constituents if the path conditions allow it.

The rest of this request is just removing all of the places where special logic was needed to allow intrinsic abstract objects to behave like they might be null or undefined.

Issue #1001.
Closes https://github.com/facebook/prepack/pull/1123

Differential Revision: D6212688

Pulled By: hermanventer

fbshipit-source-id: 8f6a24b8d8fd4afe4196f25f95ba60929ab9c788
2017-11-01 14:02:01 -07:00
Dominic Gannaway
dc27e144e9 React/JSX code cleanup in preparation for React component folding
Summary:
Release note: none

This is one part of the component folding PRs (the original has been split up). This PR makes small changes to existing code and adds in:

- a new Prepack global hook `__registerReactComponentRoot` that works in a similar way to additional functions
- some tidy up and moving around of JSX/React code
- added `checkReactRootComponents` stub function in the functions serializer code that will be used in upcoming PRs
Closes https://github.com/facebook/prepack/pull/1117

Differential Revision: D6198875

Pulled By: trueadm

fbshipit-source-id: ea183e40b8e6519a88dc574a08804e9f706c5390
2017-10-31 11:43:39 -07:00
Simon Jensen
0a3e23eeb0 Support running tests in inferior JavaScript repl.
Summary:
Define two new flags for test-runner.js:
 --repl <path> : If present the, the prepack sources of test are evaluated
using by piping to the process instead of in a new node context.
--es5 : run babel on tests, used if the repl does not support es6.

To further deal with es6 a new test header flag is introduced, es6. If a test is
not relevant in a non es6 world, the test is skipped if the es5 flag is also set.
This flag has been added to some tests.

Running subprocess for each test is obviously more expensive so the default
behavior is unchanged and still uses a new context.
Closes https://github.com/facebook/prepack/pull/1103

Differential Revision: D6192670

Pulled By: simonhj

fbshipit-source-id: 35e4b819d863634f3273a4da7984c7a71d8c4fb9
2017-10-30 17:29:46 -07:00
Herman Venter
80b0757f67 Allow required modules to throw conditionally
Summary:
Instead of delaying modules that throw conditionally, let the exception bubble up to the require call and then forget it (after emitting a warning). This allows more global state to be optimized and should be OK if it is understood that throwing an unhandled exception in module initialization code is not a supported scenario.

Probably, the temporal point where the require call happens should contain a conditional throw statement, which would be equivalent to current behavior. For now, this causes invariants to fire in the serializer, probably because of bugs in how the state at the time of the exception is restored and presented to the throw statement.

It is also an option to let the exception escape the require call itself and possibly bubble all the way to the top level. This would be more correct than the current behavior since it should match the runtime behavior of the unprepacked code. This too is currently buggy. It also a bit of performance concern because it uses much more saved state.
Closes https://github.com/facebook/prepack/pull/1104

Differential Revision: D6189032

Pulled By: hermanventer

fbshipit-source-id: 71c6352eddca4d88ae030fdcbfb76e7a39839e73
2017-10-30 13:00:01 -07:00