Commit Graph

2042 Commits

Author SHA1 Message Date
Mike Vitousek
100dfd7dab [compiler][playground] Formatting changes to pass tabs
Summary: Compiler pass tabs are bolded when their contents have changed from previous passes; but currently the HIR and JS tabs are unbolded. Conceptually they should be, if HIR is "changed" from the source code and JS is "changed" from the last IR phase.

In addition, the "show diff" option doesn't make a ton of sense for tabs that either aren't part of the pipeline (EnvironmentConfig) or (maybe more controversially, but imo) passes where the IR representation has changed since the last pass (BuildReactiveFunctions). This diff drops the button from those tabs.

ghstack-source-id: 1d67e2f371a8c75792f7f6450f52ecbf79720c00
Pull Request resolved: https://github.com/facebook/react/pull/30151
2024-07-01 09:05:52 -07:00
Mike Vitousek
9a6e2d078c [compiler] Flow support for playground
Summary: The playground currently has limited support for Flow files--it tries to parse them if the // flow sigil is on the fist line, but this is often not the case for files one would like to inspect in practice. more importantly, component syntax isn't supported even then, because it depends on the Hermes parser.

This diff improves the state of flow support in the playground to make it more useful: when we see `flow` anywhere in the file, we'll assume it's a flow file, parse it with the Hermes parser, and disable typescript-specific features of Monaco editor.

ghstack-source-id: b99b1568d7de602dd70d8cf1d8110d62530cf43b
Pull Request resolved: https://github.com/facebook/react/pull/30150
2024-07-01 09:05:52 -07:00
Mike Vitousek
d6b1c488d4 [compiler] Clone computation block in change detection mode
Summary: In change-detection mode, we previously were spreading the contents of the computation block into the result twice. Other babel passes that cause in-place mutations of the AST would then be causing action at a distance and breaking the overall transform result. This pr creates clones of the nodes instead, so that mutations aren't reflected in both places where the block is used.

ghstack-source-id: b78def8d8d1b8f9978df0a231f64fdeda786a3a3
Pull Request resolved: https://github.com/facebook/react/pull/30148
2024-06-30 22:43:32 -07:00
Mike Vitousek
fcfbfc1d1e [compiler] Always error on async reassignments
Summary: Addresses the issue in #30109: any mutation of a local in an async function may occur after rendering has finished.

ghstack-source-id: 9f15cf0f14
Pull Request resolved: https://github.com/facebook/react/pull/30111
2024-06-26 17:07:40 -07:00
Mike Vitousek
1f59d07042 [compiler] Repro for nested function local reassignment issue
Summary: Additional repro demonstrating a case that still exists after #30106

ghstack-source-id: f03176fd88
Pull Request resolved: https://github.com/facebook/react/pull/30110
2024-06-26 17:07:38 -07:00
Joe Savona
00775d94dc [compiler] Add todo fixtures for local reassignment in an async callback
ghstack-source-id: eca878f62a2149af76a72b59acd1820d0df86f30
Pull Request resolved: https://github.com/facebook/react/pull/30109
2024-06-26 16:51:15 -07:00
Joe Savona
4c9a2d2ddf [compiler] Validate against locals being reassigned after render
Adds a pass which validates that local variables are not reassigned by functions which may be called after render. This is a straightforward forward data-flow analysis, where we:
1. Build up a mapping of context variables in the outer component/hook
2. Find ObjectMethod/FunctionExpressions which may reassign those context variables
3. Propagate aliases of those functions via StoreLocal/LoadLocal
4. Disallow passing those functions with a Freeze effect. This includes JSX arguments, hook arguments, hook return types, etc.

Conceptually, a function that reassigns a local is inherently mutable. Frozen functions must be side-effect free, so these two categories are incompatible and we can use the freeze effect to find all instances of where such functions are disallowed rather than special-casing eg hook calls and JSX.

ghstack-source-id: c2b22e3d62a1ab490a6a2150e28b934b9dc8676b
Pull Request resolved: https://github.com/facebook/react/pull/30107
2024-06-26 16:51:15 -07:00
Joe Savona
b1d10c8a45 [compiler] Examples of invalid code reassigning locals outside of render
ghstack-source-id: c48d0d0b86e47e2449982263c88cc2cfd44e326b
Pull Request resolved: https://github.com/facebook/react/pull/30106
2024-06-26 16:51:15 -07:00
Sol Lee
7baae65e76 compiler: fix the hookKind for useInsertionEffect (#30069)
Currently, the `hookKind` for `useInsertionEffect` is set to
`useLayoutEffect`. This pull request fixes it by adding a new `hookKind`
for `useInsertionEffect`.
2024-06-26 14:59:03 +01:00
dependabot[bot]
bbc8851c84 Bump ws from 8.13.0 to 8.17.1 in /compiler (#30043)
Bumps [ws](https://github.com/websockets/ws) from 8.13.0 to 8.17.1.
<details>
<summary>Release notes</summary>
<p><em>Sourced from <a
href="https://github.com/websockets/ws/releases">ws's
releases</a>.</em></p>
<blockquote>
<h2>8.17.1</h2>
<h1>Bug fixes</h1>
<ul>
<li>Fixed a DoS vulnerability (<a
href="https://redirect.github.com/websockets/ws/issues/2231">#2231</a>).</li>
</ul>
<p>A request with a number of headers exceeding
the[<code>server.maxHeadersCount</code>][]
threshold could be used to crash a ws server.</p>
<pre lang="js"><code>const http = require('http');
const WebSocket = require('ws');
<p>const wss = new WebSocket.Server({ port: 0 }, function () {
const chars =
&quot;!#$%&amp;'*+-.0123456789abcdefghijklmnopqrstuvwxyz^_`|~&quot;.split('');
const headers = {};
let count = 0;</p>
<p>for (let i = 0; i &lt; chars.length; i++) {
if (count === 2000) break;</p>
<pre><code>for (let j = 0; j &amp;lt; chars.length; j++) {
  const key = chars[i] + chars[j];
  headers[key] = 'x';

  if (++count === 2000) break;
}
</code></pre>
<p>}</p>
<p>headers.Connection = 'Upgrade';
headers.Upgrade = 'websocket';
headers['Sec-WebSocket-Key'] = 'dGhlIHNhbXBsZSBub25jZQ==';
headers['Sec-WebSocket-Version'] = '13';</p>
<p>const request = http.request({
headers: headers,
host: '127.0.0.1',
port: wss.address().port
});</p>
<p>request.end();
});
</code></pre></p>
<p>The vulnerability was reported by <a
href="https://github.com/rrlapointe">Ryan LaPointe</a> in <a
href="https://redirect.github.com/websockets/ws/issues/2230">websockets/ws#2230</a>.</p>
<p>In vulnerable versions of ws, the issue can be mitigated in the
following ways:</p>
<ol>
<li>Reduce the maximum allowed length of the request headers using the
[<code>--max-http-header-size=size</code>][] and/or the
[<code>maxHeaderSize</code>][] options so
that no more headers than the <code>server.maxHeadersCount</code> limit
can be sent.</li>
</ol>
<!-- raw HTML omitted -->
</blockquote>
<p>... (truncated)</p>
</details>
<details>
<summary>Commits</summary>
<ul>
<li><a
href="3c56601092"><code>3c56601</code></a>
[dist] 8.17.1</li>
<li><a
href="e55e5106f1"><code>e55e510</code></a>
[security] Fix crash when the Upgrade header cannot be read (<a
href="https://redirect.github.com/websockets/ws/issues/2231">#2231</a>)</li>
<li><a
href="6a00029edd"><code>6a00029</code></a>
[test] Increase code coverage</li>
<li><a
href="ddfe4a804d"><code>ddfe4a8</code></a>
[perf] Reduce the amount of <code>crypto.randomFillSync()</code>
calls</li>
<li><a
href="b73b11828d"><code>b73b118</code></a>
[dist] 8.17.0</li>
<li><a
href="29694a5905"><code>29694a5</code></a>
[test] Use the <code>highWaterMark</code> variable</li>
<li><a
href="934c9d6b93"><code>934c9d6</code></a>
[ci] Test on node 22</li>
<li><a
href="1817bac06e"><code>1817bac</code></a>
[ci] Do not test on node 21</li>
<li><a
href="96c9b3dedd"><code>96c9b3d</code></a>
[major] Flip the default value of <code>allowSynchronousEvents</code>
(<a
href="https://redirect.github.com/websockets/ws/issues/2221">#2221</a>)</li>
<li><a
href="e5f32c7e1e"><code>e5f32c7</code></a>
[fix] Emit at most one event per event loop iteration (<a
href="https://redirect.github.com/websockets/ws/issues/2218">#2218</a>)</li>
<li>Additional commits viewable in <a
href="https://github.com/websockets/ws/compare/8.13.0...8.17.1">compare
view</a></li>
</ul>
</details>
<br />


[![Dependabot compatibility
score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=ws&package-manager=npm_and_yarn&previous-version=8.13.0&new-version=8.17.1)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores)

Dependabot will resolve any conflicts with this PR as long as you don't
alter it yourself. You can also trigger a rebase manually by commenting
`@dependabot rebase`.

[//]: # (dependabot-automerge-start)
[//]: # (dependabot-automerge-end)

---

<details>
<summary>Dependabot commands and options</summary>
<br />

You can trigger Dependabot actions by commenting on this PR:
- `@dependabot rebase` will rebase this PR
- `@dependabot recreate` will recreate this PR, overwriting any edits
that have been made to it
- `@dependabot merge` will merge this PR after your CI passes on it
- `@dependabot squash and merge` will squash and merge this PR after
your CI passes on it
- `@dependabot cancel merge` will cancel a previously requested merge
and block automerging
- `@dependabot reopen` will reopen this PR if it is closed
- `@dependabot close` will close this PR and stop Dependabot recreating
it. You can achieve the same result by closing it manually
- `@dependabot show <dependency name> ignore conditions` will show all
of the ignore conditions of the specified dependency
- `@dependabot ignore this major version` will close this PR and stop
Dependabot creating any more for this major version (unless you reopen
the PR or upgrade to it yourself)
- `@dependabot ignore this minor version` will close this PR and stop
Dependabot creating any more for this minor version (unless you reopen
the PR or upgrade to it yourself)
- `@dependabot ignore this dependency` will close this PR and stop
Dependabot creating any more for this dependency (unless you reopen the
PR or upgrade to it yourself)
You can disable automated security fix PRs for this repo from the
[Security Alerts
page](https://github.com/facebook/react/network/alerts).

</details>

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-06-26 09:56:13 -04:00
Mofei Zhang
d878489431 [compiler][ez] PrintHIR prints optional flag for debugging
Adding the equivalent of [PrintReactiveFunction:OptionalExpression](f5d2feb4f0/compiler/packages/babel-plugin-react-compiler/src/ReactiveScopes/PrintReactiveFunction.ts (L218)) to `PrintHIR`.

ghstack-source-id: 5b175f6f62
Pull Request resolved: https://github.com/facebook/react/pull/30078
2024-06-25 17:00:14 -04:00
Mofei Zhang
4bfab07832 [compiler][patch] Patch O(n^2) traversal in validatePreserveMemo
Double checked by syncing internally and verifying the # of `visitInstruction` calls with unique `InstructionId`s.

This is a bit of an awkward pattern though. A cleaner alternative might be to override `visitValue` and store its results in a sidemap (instead of returning)

ghstack-source-id: f6797d7652
Pull Request resolved: https://github.com/facebook/react/pull/30077
2024-06-25 17:00:14 -04:00
Mofei Zhang
7d9861e706 [compiler][hir] Correctly remove non-existent terminal preds when pruning labels
Missed this initially in `pruneUnusedLabelsHIR`. It wasn't an active bug as `preds` wasn't referenced by later passes, until #30079

ghstack-source-id: 3e151b74c3
Pull Request resolved: https://github.com/facebook/react/pull/30076
2024-06-25 17:00:13 -04:00
Mofei Zhang
9262761f1c [compiler][ez] Add more Array.prototype methods
Adds Array.prototype methods that return primitives or other arrays -- naive type inference can be really helpful in reducing mutable ranges -> achieving higher quality memoization.
Also copies Array.prototype methods to our mixed read-only JSON-like object shape.

(Inspired after going through some suboptimal internal compilation outputs.)

ghstack-source-id: 0bfad11180
Pull Request resolved: https://github.com/facebook/react/pull/30075
2024-06-25 17:00:13 -04:00
Mofei Zhang
9c2c7c670c [compiler][ez] Patch Array.concat object shape to capture callee
ghstack-source-id: 503fbf8f76
Pull Request resolved: https://github.com/facebook/react/pull/30074
2024-06-25 17:00:13 -04:00
Mofei Zhang
86d1a6f54a [compiler][rewrite] Patch logic for aligning scopes to non-value blocks
Our previous logic for aligning scopes to block scopes constructs a tree of block and scope nodes. We ensured that blocks always mapped to the same node as their fallthroughs. e.g.
```js
// source
a();
if (...) {
  b();
}
c();

// HIR
bb0:
a()
if test=... consequent=bb1 fallthrough=bb2

bb1:
b()
goto bb2

bb2:
c()

// AlignReactiveScopesToBlockScopesHIR nodes
Root node (maps to both bb0 and bb2)
  |- bb1
  |- ...
```

There are two issues with the existing implementation:
1. Only scopes that overlap with the beginning of a block are aligned correctly. This is because the traversal does not store information about the block-fallthrough pair for scopes that begin *within* the block-fallthrough range.
```
\# This case gets handled correctly
         ┌──────────────┐
         │              │
         block start    block end

scope start     scope end
│               │
└───────────────┘

\# But not this one!
┌──────────────┐
│              │
block start    block end

          scope start     scope end
          │               │
          └───────────────┘
```
2. Only scopes that are directly used by a block is considered. See the `align-scopes-nested-block-structure` fixture for details.

ghstack-source-id: 327dec5019
Pull Request resolved: https://github.com/facebook/react/pull/29891
2024-06-25 17:00:13 -04:00
Mofei Zhang
4d11e1e88d [compiler][fixtures] test repros: codegen, alignScope, phis
ghstack-source-id: 04b1526c85
Pull Request resolved: https://github.com/facebook/react/pull/29878

The AlignReactiveScope bug should be simplest to fix, but it's also caught by an invariant assertion. I think a fix could be either keeping track of "active" block-fallthrough pairs (`retainWhere(pair => pair.range.end > current.instr[0].id)`) or following the approach in `assertValidBlockNesting`.
I'm tempted to pull the value-block aligning logic out into its own pass (using the current `node` tree traversal), then align to non-value blocks with the `assertValidBlockNesting` approach. Happy to hear feedback on this though!

The other two are likely bigger issues, as they're not caught by static invariants.

Update:
- removed bug-phi-reference-effect as it's been patched by @josephsavona
- added bug-array-concat-should-capture
2024-06-25 17:00:13 -04:00
Lauren Tan
708d8f8c49 [ez] Remove outdated files
These are no longer in use

ghstack-source-id: 075e4fd0ab
Pull Request resolved: https://github.com/facebook/react/pull/30092
2024-06-25 14:09:04 -04:00
Lauren Tan
f6b546737e Bump version to 0.0.0-experimental-b130d5f-20240625 2024-06-25 12:42:06 -04:00
Lauren Tan
bdb355f349 Bump version to 0.0.0-experimental-0998c1e-20240625 2024-06-25 12:42:06 -04:00
Lauren Tan
d17f024681 Bump version to 0.0.0-experimental-696af53-20240625 2024-06-25 12:42:06 -04:00
Sathya Gunasekaran
8971381549 [compiler] Enable sourceMaps in tsconfig (#30064)
With this, we can set a `debugger` breakpoint and we'll break into the
source code when running tests with snap. Without this, we'd break into
the transpiled js code.
2024-06-25 17:01:43 +01:00
Joe Savona
f5d2feb4f0 [compiler] Fix assignment within for update expression
When converting value blocks from HIR to ReactiveFunction, we have to drop StoreLocal assignments that represent the assignment of the phi, since ReactiveFunction supports compound expressions. These StoreLocals are only present to represent the conditional assignment of the value itself - but it's also possible for the expression to have contained an assignment expression. Before, in trying to strip the first category of StoreLocal we also accidentally stripped the second category. Now we check that the assignment is for a temporary, and don't strip otherwise.

ghstack-source-id: e7759c963bbc1bbff2d3230534b049199e3262ad
Pull Request resolved: https://github.com/facebook/react/pull/30067
2024-06-24 10:49:36 -07:00
Joe Savona
454fb35065 [compiler] add fixture for optimization across scopes
Adds a fixture based on internal case where our current output is quite a bit more verbose than the original memoization. See the comment in the fixture for more about the heuristic we can apply.

ghstack-source-id: e637a38140
Pull Request resolved: https://github.com/facebook/react/pull/29998
2024-06-21 16:48:14 -07:00
Joe Savona
2caaa05c08 [compiler] Optimize instruction reordering
Note: due to a bad rebase i included #29883 here. Both were stamped so i'm not gonna bother splitting it back up aain.

This PR includes two changes:
* First, allow `LoadLocal` to be reordered if a) the load occurs after the last write to a variable and b) the LoadLocal lvalue is used exactly once
* Uses a more optimal reordering for statement blocks, while keeping the existing approach for expression blocks.

In #29863 I tried to find a clean way to share code for emitting instructions between value blocks and regular blocks. The catch is that value blocks have special meaning for their final instruction — that's the value of the block — so reordering can't change the last instruction. However, in finding a clean way to share code for these two categories of code, i also inadvertently reduced the effectiveness of the optimization.

This PR updates to use different strategies for these two kinds of blocks: value blocks use the code from #29863 where we first emit all non-reorderable instructions in their original order, then try to emit reorderable values. The reason this is suboptimal, though, is that we want to move instructions closer to their dependencies so that they can invalidate (merge) together. Emitting the reorderable values last prevents this.

So for normal blocks, we now emit terminal operands first. This will invariably cause some of the non-reorderable instructions to be emitted, but it will intersperse reoderable instructions in between, right after their dependencies. This maximizes our ability to merge scopes.

I think the complexity cost of two strategies is worth the benefit, as evidenced by the reduced memo slots in the fixtures.

ghstack-source-id: ad3e516fa4
Pull Request resolved: https://github.com/facebook/react/pull/29882
2024-06-21 16:48:14 -07:00
Lauren Tan
3776e98f90 [prettier] Run prettier
ghstack-source-id: 80f1247d5d
Pull Request resolved: https://github.com/facebook/react/pull/30022
2024-06-21 12:05:29 -04:00
Lauren Tan
49c37048de [prettier] Combine compiler and runtime configs
Merges the existing config to the root one so we can have a single
configuration file. I've tried to keep the compiler config as much as
possible in this PR so that no formatting changes occur.

ghstack-source-id: 8bbfc9f269
Pull Request resolved: https://github.com/facebook/react/pull/30021
2024-06-21 12:05:29 -04:00
Lauren Tan
49a4887586 [compiler:codegen] Wrap non-ascii characters in JsxExpressionContainer
This PR extends the previous logic added in #29141 to also account for
other kinds of non-ascii characters such as `\n`. Because these control
characters are individual special characters (and not 2 characters `\`
and `n`) we match based on unicode which was already being checked for
non-Latin characters.

This allows control characters to continue to be compiled equivalently
to its original source if it was provided in a JsxExpressionContainer.
However note that this PR does not convert JSX attributes that are
StringLiterals to JsxExpressionContainer, to preserve the original
source code as it was written.

Alternatively we could always emit a JsxExpressionContainer if it was
used in the source and not try to down level it to some other node
kind. But since we already do this I opted to keep this behavior.

Partially addresses #29648.

ghstack-source-id: ecc61c9f0bece90d18623b3c570fea05fbcd811a
Pull Request resolved: https://github.com/facebook/react/pull/29997
2024-06-21 10:08:15 -04:00
NISHIZAWA Shuntaro
a5554190c1 fix[compiler playground]: Set source as the pre-change state in HIR diff (#29957)
<!--
  Thanks for submitting a pull request!
We appreciate you spending the time to work on these changes. Please
provide enough information so that others can review your pull request.
The three fields below are mandatory.

Before submitting a pull request, please make sure the following is
done:

1. Fork [the repository](https://github.com/facebook/react) and create
your branch from `main`.
  2. Run `yarn` in the repository root.
3. If you've fixed a bug or added code that should be tested, add tests!
4. Ensure the test suite passes (`yarn test`). Tip: `yarn test --watch
TestName` is helpful in development.
5. Run `yarn test --prod` to test in the production environment. It
supports the same options as `yarn test`.
6. If you need a debugger, run `yarn test --debug --watch TestName`,
open `chrome://inspect`, and press "Inspect".
7. Format your code with
[prettier](https://github.com/prettier/prettier) (`yarn prettier`).
8. Make sure your code lints (`yarn lint`). Tip: `yarn linc` to only
check changed files.
  9. Run the [Flow](https://flowtype.org/) type checks (`yarn flow`).
  10. If you haven't already, complete the CLA.

Learn more about contributing:
https://reactjs.org/docs/how-to-contribute.html
-->

## Summary

<!--
Explain the **motivation** for making this change. What existing problem
does the pull request solve?
-->

I have fixed an issue where the display of the HIR diff in the React
Compiler Playground was incorrect. The HIR diff is supposed to show the
pre-change state as the source, but currently, it is showing
EnvironmentConfig as the pre-change state. This PR corrects this by
setting the pre-change state to source instead of EnvironmentConfig.

## How did you test this change?

<!--
Demonstrate the code is solid. Example: The exact commands you ran and
their output, screenshots / videos if the pull request changes the user
interface.
How exactly did you verify that your PR solves the issue you wanted to
solve?
  If you leave this empty, your PR will very likely be closed.
-->

before:


![image](https://github.com/facebook/react/assets/37236438/c98aee7a-b569-430e-8698-0f7eff6c21e2)

after:


![image](https://github.com/facebook/react/assets/37236438/6113297c-80f9-4e71-a0d1-df8cc87507db)
2024-06-20 12:01:35 -04:00
Sathya Gunasekaran
83d538e0d0 [compiler] Treat ref-like named objects as refs (#29916)
If a component uses the `useRef` hook directly then we type it's return
value as a ref. But if it's wrapped in a custom hook then we lose out on
this type information as the compiler doesn't look at the hook
definition. This has resulted in some false positives in our analysis
like the ones reported in #29160 and #29196.

This PR will treat objects named as `ref` or if their names end with the
substring `Ref`, and contain a property named `current`, as React refs.

```
const ref = useMyRef();
const myRef = useMyRef2();
useEffect(() => {
  ref.current = ...;
  myRef.current = ...;
})
```
In the above example, `ref` and `myRef` will be treated as React refs.
2024-06-18 18:02:19 +01:00
Joseph Savona
ddcecbbebf Consider dispatch function from useActionState non-reactive (#29917)
Updated version of #29758 removing `useFormState` since that was the
previous name for `useActionState`.

---------

Co-authored-by: Hieu Do <hieudn.uh@gmail.com>
2024-06-17 12:26:55 -07:00
Joe Savona
dbc5f36fe9 [compiler] Support method-call version of macro functions
Adds fixtures for `macro.namespace(...)` style invocations which we use internally in some cases instead of just `macro(...)`. I tried every example i could think of that could possibly break it (including basing one off of another fixture where we hit an invariant related due to a temporary being emitted for a method call), and they all worked. I just had to fix an existing bug where we early return in some cases instead of continuing, which is a holdover from when this pass was originally written as a ReactiveFunction visitor.

ghstack-source-id: c01f45b3ef6f42b6d1f1ff0508aea258000e0fce
Pull Request resolved: https://github.com/facebook/react/pull/29899
2024-06-17 08:17:24 -07:00
Lauren Tan
05a3a7fa8d Bump version to 0.0.0-experimental-c20572a-20240614 2024-06-14 17:21:59 -04:00
Lauren Tan
d46985282d Bump version to 0.0.0-experimental-8ae29d2-20240614 2024-06-14 17:21:59 -04:00
Lauren Tan
7f9fbeafd5 Bump version to 0.0.0-experimental-179941d-20240614 2024-06-14 17:21:59 -04:00
Joe Savona
59e73d9016 [compiler] Instruction reordering
Adds a pass just after DCE to reorder safely reorderable instructions (jsx, primitives, globals) closer to where they are used, to allow other optimization passes to be more effective. Notably, the reordering allows scope merging to be more effective, since that pass relies on two scopes not having intervening instructions — in many cases we can now reorder such instructions out of the way and unlock merging, as demonstrated in the changed fixtures.

The algorithm itself is described in the docblock.

note: This is a cleaned up version of #29579 that is ready for review.

ghstack-source-id: c54a806cad
Pull Request resolved: https://github.com/facebook/react/pull/29863
2024-06-14 14:14:42 -07:00
Joe Savona
ed8dd2036b [compiler] Allow more instruction kinds btw merged scopes
Updates our scope merging pass to allow more types of instructions to intervene btw scopes. This includes all the non-allocating kinds of nodes that are considered reorderable in #29863. It's already safe to merge scopes with these instructions — we only merge if the lvalue is not used past the next scope. Additionally, without changing this pass reordering isn't very effective, since we would reorder to add these types of intervening instructions and then not be able to merge scopes.

Sequencing this first helps to see the win just from reordering alone.

ghstack-source-id: 79263576d8
Pull Request resolved: https://github.com/facebook/react/pull/29881
2024-06-14 14:14:42 -07:00
Joe Savona
a07f5a3db5 [compiler] Provide support for custom fbt-like macro functions
ghstack-source-id: e3c6455ac2
Pull Request resolved: https://github.com/facebook/react/pull/29893
2024-06-13 17:36:37 -07:00
Mike Vitousek
2ba462b665 [compiler][playground] Make change detection work in playground
Summary: The change detection mode was unavailable in the playground because the pragma was not a boolean. This fixes that by special casing it in pragma parsing, similar to validateNoCapitalizedCalls

ghstack-source-id: 4a8c17d21ab8b7936ca61c9dd1f7fdf8322614c9
Pull Request resolved: https://github.com/facebook/react/pull/29889
2024-06-13 11:02:47 -07:00
Joe Savona
ca9b6a7ebc [compiler] Fix visitors to emit the correct kind
Our passes aren't sequenced such that we could observe this bug, but this retains the proper terminal kind for pruned-scopes in mapTerminalSuccessors.

ghstack-source-id: 1a03b40e45649bbef7d6db968fb2dbd6261a246a
Pull Request resolved: https://github.com/facebook/react/pull/29884
2024-06-13 08:02:08 -07:00
Mike Vitousek
814a418645 [compiler] Make unary and binary operator types more precise
Summary: Minor change inspired by #29863: the BuildHIR pass ensures that Binary and UnaryOperator nodes only use a limited set of the operators that babel's operator types represent, which that pr relies on for safe reorderability, but the type of those HIR nodes admits the other operators. For example, even though you can't build an HIR UnaryOperator with `delete` as the operator, it is a valid HIR node--and if we made a mistaken change that let you build such a node, it would be unsafe to reorder.

This pr makes the typing of operators stricter to prevent that.

ghstack-source-id: 9bf3b1a37eae3f14c0e9fb42bb3ece522b317d98
Pull Request resolved: https://github.com/facebook/react/pull/29880
2024-06-12 15:31:59 -07:00
Joe Savona
55fdcf87bd [compiler] Fix merging of queued states in InferReferenceEffects
Fixes a bug found by mofeiZ in #29878. When we merge queued states, if the new state does not introduce changes relative to the queued state we should use the queued state, not the new state.

ghstack-source-id: c59f69de15
Pull Request resolved: https://github.com/facebook/react/pull/29879
2024-06-12 14:49:23 -07:00
Mike Vitousek
a26e3f403e [compiler] Expect component props annotations to be potential objects
Summary: We now expect that candidate components that have Flow or TS type annotations on their first parameters have annotations that are potentially objects--this lets us reject compiling functions that explicitly take e.g. `number` as a parameter.

ghstack-source-id: e2c23348265b7ef651232b962ed7be7f6fed1930
Pull Request resolved: https://github.com/facebook/react/pull/29866
2024-06-11 14:08:21 -07:00
Mike Vitousek
057de295d5 [compiler] Expect components to have hook calls or jsx directly in body
Summary: We can tighten our criteria for what is a component by requiring that a component or hook contain JSX or hook calls directly within its body, excluding nested functions . Currently, if we see them within the body anywhere -- including nested functions -- we treat it as a component if the other requirements are met. This change makes this stricter.

We also now expect components (but not necessarily hooks) to have return statements, and those returns must be potential React nodes (we can reject functions that return function or object literals, for example).

ghstack-source-id: 4507cc3955216c564bf257c0b81bfb551ae6ae55
Pull Request resolved: https://github.com/facebook/react/pull/29865
2024-06-11 14:08:21 -07:00
Mike Vitousek
3cd3735515 [compiler] Option to only compile component syntax
Summary: Projects which have heavily adopted Flow component syntax may wish to enable the compiler only for components and hooks that use the syntax, rather than trying to guess which functions are components and hooks. This provides that option.

ghstack-source-id: 579ac9f0fa01d8cdb6a0b8f9923906a0b37662f3
Pull Request resolved: https://github.com/facebook/react/pull/29864
2024-06-11 14:08:21 -07:00
Lauren Tan
82dea10511 [compiler] Remove .vscode
To keep consistent with the rest of the React repo, let's remove this
because editor settings are personal. Additionally this wasn't in the
root directory so it wasn't being applied anyway.

ghstack-source-id: 3a2e2993d6
Pull Request resolved: https://github.com/facebook/react/pull/29861
2024-06-11 15:25:05 -04:00
Joe Savona
b5b9daa44d [compiler] HIR-based FlattenScopesWithHooksOrUse
Per title, implements an HIR-based version of FlattenScopesWithHooksOrUse as part of our push to use HIR everywhere. This is the last pass to migrate before PropagateScopeDeps, which is blocking the fix for `bug.invalid-hoisting-functionexpr`, ie where we can infer incorrect dependencies for function expressions if the dependencies are accessed conditionally.

ghstack-source-id: 05c6e26b3b7a3b1c3e106a37053f88ac3c72caf5
Pull Request resolved: https://github.com/facebook/react/pull/29840
2024-06-11 08:34:59 -07:00
Joe Savona
43c17d13ef [compiler] HIR-based FlattenReactiveLoops
Pre the title, this implements an HIR-based version of FlattenReactiveLoops. Another step on the way to HIR-everywhere.

ghstack-source-id: e1d166352df6b0725e4c4915a19445437916251f
Pull Request resolved: https://github.com/facebook/react/pull/29838
2024-06-11 08:34:59 -07:00
Joe Savona
f7b871a8d5 [compiler] Add pruned-scope terminal in HIR
Adds the HIR equivalent of a pruned-scope, allowing us to start porting the scope-pruning passes to operate on HIR.

ghstack-source-id: dbbdc43219123467acc1a531d8276e8b9cc91e14
Pull Request resolved: https://github.com/facebook/react/pull/29837
2024-06-11 08:34:59 -07:00
Lauren Tan
c015abd9dc [compiler] Remove unused scripts
ghstack-source-id: ae0c1bf365
Pull Request resolved: https://github.com/facebook/react/pull/29842
2024-06-10 20:35:40 -04:00