Commit Graph

2498 Commits

Author SHA1 Message Date
Joseph Savona 2bee34867d [compiler] Cleanup debugging code (#33571)
Removes unnecessary debugging code in the new inference passes now that
they've stabilized more.

---
[//]: # (BEGIN SAPLING FOOTER)
Stack created with [Sapling](https://sapling-scm.com). Best reviewed
with [ReviewStack](https://reviewstack.dev/facebook/react/pull/33571).
* __->__ #33571
* #33558
* #33547
2025-06-18 16:00:55 -07:00
Joseph Savona d37faa041b [compiler] Preserve Create effects, guarantee effects initialize once (#33558)
Ensures that effects are well-formed with respect to the rules:
* For a given instruction, each place is only initialized once (w one of
Create, CreateFrom, Assign)
* Ensures that Alias targets are already initialized within the same
instruction (should have a Create before them)
* Preserves Create and similar instructions
* Avoids duplicate instructions when inferring effects of function
expressions

---
[//]: # (BEGIN SAPLING FOOTER)
Stack created with [Sapling](https://sapling-scm.com). Best reviewed
with [ReviewStack](https://reviewstack.dev/facebook/react/pull/33558).
* #33571
* __->__ #33558
* #33547
2025-06-18 16:00:45 -07:00
Joseph Savona 3a2ff8b51b [compiler] Fix <ValidateMemoization> (#33547)
By accident we were only ever checking the compiled output, but the
intention was in general to be able to compare memoization with/without
forget.

---
[//]: # (BEGIN SAPLING FOOTER)
Stack created with [Sapling](https://sapling-scm.com). Best reviewed
with [ReviewStack](https://reviewstack.dev/facebook/react/pull/33547).
* #33571
* #33558
* __->__ #33547
2025-06-18 16:00:36 -07:00
Joseph Savona cc3806377a [compiler] Tests for different orders of createfrom/capture w/wo function expressions (#33543)
Adds some typed helpers to represent aliasing, assign, capture,
createfrom, and mutate effects along with representative runtime
behavior, and then adds tests to demonstrate that we model
capture->createfrom and createfrom->capture correctly.

There is one case (createfrom->capture in a lambda) where we infer a
less precise effect, but in the more conservative direction (we include
more code/deps than necesssary rather than fewer).

---
[//]: # (BEGIN SAPLING FOOTER)
Stack created with [Sapling](https://sapling-scm.com). Best reviewed
with [ReviewStack](https://reviewstack.dev/facebook/react/pull/33543).
* #33571
* #33558
* #33547
* __->__ #33543
2025-06-18 15:56:27 -07:00
Joseph Savona 4f543f326c [compiler] Docs describing new inference model (#33533)
Start of docs describing the effects and the inference rules.

---
[//]: # (BEGIN SAPLING FOOTER)
Stack created with [Sapling](https://sapling-scm.com). Best reviewed
with [ReviewStack](https://reviewstack.dev/facebook/react/pull/33533).
* #33571
* #33558
* #33547
* #33543
* __->__ #33533
* #33532
* #33530
2025-06-18 15:48:01 -07:00
Joseph Savona 7ceb10035f [compiler] Rename InferFunctionExprAliasingEffectsSignature (#33532)
---
[//]: # (BEGIN SAPLING FOOTER)
Stack created with [Sapling](https://sapling-scm.com). Best reviewed
with [ReviewStack](https://reviewstack.dev/facebook/react/pull/33532).
* #33571
* #33558
* #33547
* #33543
* #33533
* __->__ #33532
* #33530
2025-06-18 15:47:52 -07:00
Joseph Savona 4335f69987 [compiler] More readable alias signature declarations (#33530)
Now that we have support for defining aliasing signatures in
moduleTypeProvider, which uses string names for
receiver/args/returns/etc, we can reuse that same form for builtin
declarations. The declarations are written in the unparsed form and than
parsed/validated when registered (in the addFunction/addHook call).

This also required flushing out configs/schemas for more effect types.

---
[//]: # (BEGIN SAPLING FOOTER)
Stack created with [Sapling](https://sapling-scm.com). Best reviewed
with [ReviewStack](https://reviewstack.dev/facebook/react/pull/33530).
* #33571
* #33558
* #33547
* #33543
* #33533
* #33532
* __->__ #33530
2025-06-18 15:47:43 -07:00
Joseph Savona 34179fe344 [compiler] moduleTypeProvider support for aliasing signatures (#33526)
This allows us to type things like `nullthrows()` or `identity()`
functions where the return type is polymorphic on the input.

---
[//]: # (BEGIN SAPLING FOOTER)
Stack created with [Sapling](https://sapling-scm.com). Best reviewed
with [ReviewStack](https://reviewstack.dev/facebook/react/pull/33526).
* #33571
* #33558
* #33547
* #33543
* #33533
* #33532
* #33530
* __->__ #33526
* #33522
* #33518
2025-06-18 15:43:48 -07:00
Joseph Savona 0e7cdebb32 [compiler] Repro for case of lost precision in new inference (#33522)
In comparing compilation output of the old/new inference models I found
this case (heavily distilled into a fixture). Roughly speaking the
scenario is:

* Create a mutable object `x`
* Extract part of that object and pass it to a hook/jsx so that _part_
becomes frozen
* Mutate `x`, even indirectly.

In the old model we can still independently memoize the value from the
middle step, since we assume that part of the larger value is not
changing. In the new model, the mutation from the later step effectively
overrides the freeze effect in step 2, and considers the value to have
changed later anyway.

We've already rolled out and vetted the previous behavior, confirming
that the heuristic of "that part of the mutable object is fozen now" is
generally safe. I'll fix in a follow-up.

---
[//]: # (BEGIN SAPLING FOOTER)
Stack created with [Sapling](https://sapling-scm.com). Best reviewed
with [ReviewStack](https://reviewstack.dev/facebook/react/pull/33522).
* #33571
* #33558
* #33547
* #33543
* #33533
* #33532
* #33530
* #33526
* __->__ #33522
* #33518
2025-06-18 15:43:33 -07:00
Joseph Savona 81d8115116 [compiler] Fix infinite loop due to uncached applied signatures (#33518)
When we apply new aliasing signatures we can generate new temporaries,
which causes the abstract memory model to not converge. The fix is to
make sure we cache the applications of these signatures.

---
[//]: # (BEGIN SAPLING FOOTER)
Stack created with [Sapling](https://sapling-scm.com). Best reviewed
with [ReviewStack](https://reviewstack.dev/facebook/react/pull/33518).
* #33571
* #33558
* #33547
* #33543
* #33533
* #33532
* #33530
* #33526
* #33522
* __->__ #33518
2025-06-18 15:43:23 -07:00
Joseph Savona 8f4ce72f0b [commit] Improve error for hoisting violations (#33514)
The previous error for hoisting violations pointed only to the variable
declaration, but didn't show where the value was accessed before that
declaration. We now track where each hoisted variable is first accessed
and report two errors, one for the reference and one for the
declaration. When we improve our diagnostic infra to support reporting
errors at multiple locations we can merge these into a single conceptual
error.

---
[//]: # (BEGIN SAPLING FOOTER)
Stack created with [Sapling](https://sapling-scm.com). Best reviewed
with [ReviewStack](https://reviewstack.dev/facebook/react/pull/33514).
* #33571
* #33558
* #33547
* #33543
* #33533
* #33532
* #33530
* #33526
* #33522
* #33518
* __->__ #33514
* #33573
2025-06-18 15:24:41 -07:00
Joseph Savona 7ce2a63acc [compiler] update fixtures (#33573)
---
[//]: # (BEGIN SAPLING FOOTER)
Stack created with [Sapling](https://sapling-scm.com). Best reviewed
with [ReviewStack](https://reviewstack.dev/facebook/react/pull/33573).
* #33571
* #33558
* #33547
* #33543
* #33533
* #33532
* #33530
* #33526
* #33522
* #33518
* #33514
* __->__ #33573
2025-06-18 15:24:30 -07:00
Joseph Savona b067c6fe79 [compiler] Improve error message for mutating hook args/return (#33513)
The previous error message was generic, because the old style function
signature didn't support a way to specify a reason alongside a freeze
effect. This meant we could only say why a value was frozen for
instructions, but not hooks which use function signatures. By defining a
new aliasing signature for custom hooks we can specify a reason and
provide a better error message.

---
[//]: # (BEGIN SAPLING FOOTER)
Stack created with [Sapling](https://sapling-scm.com). Best reviewed
with [ReviewStack](https://reviewstack.dev/facebook/react/pull/33513).
* #33571
* #33558
* #33547
* #33543
* #33533
* #33532
* #33530
* #33526
* #33522
* #33518
* #33514
* __->__ #33513
2025-06-18 13:04:53 -07:00
Joseph Savona e081cb3446 [compiler] FunctionExpression context locations point to first reference (#33512)
This has always been awkward: `FunctionExpression.context` places have
locations set to the declaration of the identifier, whereas other
references have locations pointing to the reference itself. Here, we
update context operands to have their location point to the first
reference of that variable within the function.

---
[//]: # (BEGIN SAPLING FOOTER)
Stack created with [Sapling](https://sapling-scm.com). Best reviewed
with [ReviewStack](https://reviewstack.dev/facebook/react/pull/33512).
* #33571
* #33558
* #33547
* #33543
* #33533
* #33532
* #33530
* #33526
* #33522
* #33518
* #33514
* #33513
* __->__ #33512
* #33504
* #33500
* #33497
* #33496
2025-06-18 13:02:43 -07:00
Joseph Savona 7b67dc92b0 [commit] Better error message for invalid hoisting (#33504)
We're already tracking which variables are hoisted context variables, so
if we see a mutation of a frozen value we can emit a custom error
message to help users identify the problem.

---
[//]: # (BEGIN SAPLING FOOTER)
Stack created with [Sapling](https://sapling-scm.com). Best reviewed
with [ReviewStack](https://reviewstack.dev/facebook/react/pull/33504).
* #33571
* #33558
* #33547
* #33543
* #33533
* #33532
* #33530
* #33526
* #33522
* #33518
* #33514
* #33513
* #33512
* __->__ #33504
* #33500
* #33497
* #33496
2025-06-18 13:02:32 -07:00
Joseph Savona 7c28c15465 [compiler] Fix AnalyzeFunctions to fully reset context identifiers (#33500)
AnalyzeFunctions had logic to reset the mutable ranges of context
variables after visiting inner function expressions. However, there was
a bug in that logic: InferReactiveScopeVariables makes all the
identifiers in a scope point to the same mutable range instance. That
meant that it was possible for a later function expression to indirectly
cause an earlier function expressions' context variables to get a
non-zero mutable range.

The fix is to not just reset start/end of context var ranges, but assign
a new range instance. Thanks for the help on debugging, @mofeiz!

---
[//]: # (BEGIN SAPLING FOOTER)
Stack created with [Sapling](https://sapling-scm.com). Best reviewed
with [ReviewStack](https://reviewstack.dev/facebook/react/pull/33500).
* #33571
* #33558
* #33547
* #33543
* #33533
* #33532
* #33530
* #33526
* #33522
* #33518
* #33514
* #33513
* #33512
* #33504
* __->__ #33500
* #33497
* #33496
2025-06-18 13:02:23 -07:00
Joseph Savona 90ccbd71c1 [compiler] Enable new inference by default (#33497)
---
[//]: # (BEGIN SAPLING FOOTER)
Stack created with [Sapling](https://sapling-scm.com). Best reviewed
with [ReviewStack](https://reviewstack.dev/facebook/react/pull/33497).
* #33571
* #33558
* #33547
* #33543
* #33533
* #33532
* #33530
* #33526
* #33522
* #33518
* #33514
* #33513
* #33512
* #33504
* #33500
* __->__ #33497
* #33496
2025-06-18 13:02:12 -07:00
Joseph Savona 0cf6d0c929 [compiler] Update fixtures for new inference (#33496)
---
[//]: # (BEGIN SAPLING FOOTER)
Stack created with [Sapling](https://sapling-scm.com). Best reviewed
with [ReviewStack](https://reviewstack.dev/facebook/react/pull/33496).
* #33571
* #33558
* #33547
* #33543
* #33533
* #33532
* #33530
* #33526
* #33522
* #33518
* #33514
* #33513
* #33512
* #33504
* #33500
* #33497
* __->__ #33496
2025-06-18 13:01:56 -07:00
Joseph Savona df080d228b [compiler] Copy fixtures affected by new inference (#33495)
---
[//]: # (BEGIN SAPLING FOOTER)
Stack created with [Sapling](https://sapling-scm.com). Best reviewed
with [ReviewStack](https://reviewstack.dev/facebook/react/pull/33495).
* #33571
* #33558
* #33547
* #33543
* #33533
* #33532
* #33530
* #33526
* #33522
* #33518
* #33514
* #33513
* #33512
* #33504
* #33500
* #33497
* #33496
* __->__ #33495
* #33494
* #33572
2025-06-18 12:58:16 -07:00
Joseph Savona 66cfe048d3 [compiler] New mutability/aliasing model (#33494)
Squashed, review-friendly version of the stack from
https://github.com/facebook/react/pull/33488.

This is new version of our mutability and inference model, designed to
replace the core algorithm for determining the sets of instructions
involved in constructing a given value or set of values. The new model
replaces InferReferenceEffects, InferMutableRanges (and all of its
subcomponents), and parts of AnalyzeFunctions. The new model does not
use per-Place effect values, but in order to make this drop-in the end
_result_ of the inference adds these per-Place effects.

I'll write up a larger document on the model, first i'm doing some
housekeeping to rebase the PR.

---
[//]: # (BEGIN SAPLING FOOTER)
Stack created with [Sapling](https://sapling-scm.com). Best reviewed
with [ReviewStack](https://reviewstack.dev/facebook/react/pull/33494).
* #33571
* #33558
* #33547
* #33543
* #33533
* #33532
* #33530
* #33526
* #33522
* #33518
* #33514
* #33513
* #33512
* #33504
* #33500
* #33497
* #33496
* #33495
* __->__ #33494
* #33572
2025-06-18 12:58:06 -07:00
Joseph Savona ae962653d6 [compiler] Remove unnecessary fixture (#33572)
This is covered by iife-inline-ternary

---
[//]: # (BEGIN SAPLING FOOTER)
Stack created with [Sapling](https://sapling-scm.com). Best reviewed
with [ReviewStack](https://reviewstack.dev/facebook/react/pull/33572).
* #33571
* #33558
* #33547
* #33543
* #33533
* #33532
* #33530
* #33526
* #33522
* #33518
* #33514
* #33513
* #33512
* #33504
* #33500
* #33497
* #33496
* #33495
* #33494
* __->__ #33572
2025-06-18 12:57:54 -07:00
Jordan Brown 90bee81902 [compiler] Do not inline IIFEs in value blocks (#33548)
As discussed in chat, this is a simple fix to stop introducing labels
inside expressions.

The useMemo-with-optional test was added in
https://github.com/facebook/react/commit/d70b2c2c4e85c2a7061214c15a8ff13167d10422
and crashes for the same reason- an unexpected label as a value block
terminal.

---
[//]: # (BEGIN SAPLING FOOTER)
Stack created with [Sapling](https://sapling-scm.com). Best reviewed
with [ReviewStack](https://reviewstack.dev/facebook/react/pull/33548).
* __->__ #33548
* #33546
2025-06-16 21:53:50 -04:00
Jordan Brown 75e78d243f [compiler] Add repro for IIFE in ternary causing a bailout (#33546)
---
[//]: # (BEGIN SAPLING FOOTER)
Stack created with [Sapling](https://sapling-scm.com). Best reviewed
with [ReviewStack](https://reviewstack.dev/facebook/react/pull/33546).
* #33548
* __->__ #33546
2025-06-16 21:53:27 -04:00
lauren 888ea60d8e [compiler][repro] Postfix operator is incorrectly compiled (#33508)
This bug was reported via our wg and appears to only affect values
created as a ref.

Currently, postfix operators used in a callback gets compiled to:

```js
modalId.current = modalId.current + 1; // 1
const id = modalId.current; // 1
return id;
```

which is semantically incorrect. The postfix increment operator should
return the value before incrementing. In other words something like this
should have been compiled instead:

```js
const id = modalId.current; // 0
modalId.current = modalId.current + 1; // 1
return id;
```

This bug does not trigger when the incremented value is a plain
primitive, instead there is a TODO bailout.
2025-06-11 14:40:42 -04:00
Wesley LeMahieu b6c0aa8814 [compiler]: fix link compiler & 4 broken tests from path containing spaces (#33409)
## Summary

Problem #1: Running the `link-compiler.sh` bash script via `"prebuild"`
script fails if a developer has cloned the `react` repo into a folder
that contains _any_ spaces. 3 tests fail because of this.

<img width="1003" alt="fail-1"
src="https://github.com/user-attachments/assets/1fbfa9ce-4f84-48d7-b49c-b6e967b8c7ca"
/>
<img width="1011" alt="fail-2"
src="https://github.com/user-attachments/assets/0a8c6371-a2df-4276-af98-38f4784cf0da"
/>
<img width="1027" alt="fail-3"
src="https://github.com/user-attachments/assets/1c4f4429-800c-4b44-b3da-a59ac85a16b9"
/>

For example, my current folder is:
`/Users/wes/Development/Open Source Contributions/react`

The link compiler error returns:
`./scripts/react-compiler/link-compiler.sh: line 15: cd:
/Users/wes/Development/Open: No such file or directory`

Problem #2: 1 test in `ReactChildren-test.js` fails due the existing
stack trace regex which should be lightly revised.

`([^(\[\n]+)[^\n]*/g` is more robust for stack traces: it captures the
function/class name (with dots) and does not break on spaces in file
paths.
`([\S]+)[^\n]*/g` is simpler but breaks if there are spaces and doesn't
handle dotted names well.

Additionally, we trim the whitespace off the name to resolve extra
spaces breaking this test as well:

```
-     in div (at **)
+     in div  (at **)
```

<img width="987" alt="fail-4"
src="https://github.com/user-attachments/assets/56a673bc-513f-4458-95b2-224129c77144"
/>

All of the above tests pass if I hyphenate my local folder:
`/Users/wes/Development/Open-Source-Contributions/react`

I selfishly want to keep spaces in my folder names. 🫣

## How did you test this change?

**npx yarn prebuild**

Before:
<img width="896" alt="Screenshot at Jun 01 11-42-56"
src="https://github.com/user-attachments/assets/4692775c-1e5c-4851-9bd7-e12ed5455e47"
/>

After:
<img width="420" alt="Screenshot at Jun 01 11-43-42"
src="https://github.com/user-attachments/assets/4e303c00-02b7-4540-ba19-927b2d7034fb"
/>

**npx yarn test**
**npx yarn test
./packages/react/src/\_\_tests\_\_/ReactChildren-test.js**
**npx yarn test -r=xplat --env=development --variant=true --ci
--shard=3/5**

Before:
<img width="438" alt="before"
src="https://github.com/user-attachments/assets/f5eedb22-18c3-4124-a04b-daa95c0f7652"
/>

After:
<img width="439" alt="after"
src="https://github.com/user-attachments/assets/a94218ba-7c6a-4f08-85d3-57540e9d0029"
/>

<img width="650" alt="Screenshot at Jun 02 18-03-39"
src="https://github.com/user-attachments/assets/3eae993c-a56b-46c8-ae02-d249cb053fe7"
/>

<img width="685" alt="Screenshot at Jun 03 12-53-47"
src="https://github.com/user-attachments/assets/5b2caa33-d3dc-4804-981d-52cb10b6226f"
/>
2025-06-09 08:40:27 -07:00
Jordan Brown 4df098c4c2 [compiler] Don't include useEffectEvent values in autodeps (#33450)
Summary: useEffectEvent values are not meant to be added to the dep
array
2025-06-09 09:26:45 -04:00
Jorge Cabiedes 2b4064eb9b [mcp] Add MCP tool to print out the component tree of the currently open React App (#33305)
## Summary

This tool leverages DevTools to get the component tree from the
currently open React App. This gives realtime information to agents
about the state of the app.

## How did you test this change?

Tested integration with Claude Desktop
2025-06-02 21:42:34 -07:00
Ricky 3531b26729 [scripts] Switch back to flow parser for prettier (#33414)
Prettier 3.3 (which we're on) should support modern flow features
according to https://prettier.io/blog/2024/06/01/3.3.0
2025-06-03 00:00:28 -04:00
mofeiZ 526dd340b3 [compiler][patch] Emit unary expressions instead of negative numbers (#33383)
This is a babel bug + edge case.

Babel compact mode produces invalid JavaScript (i.e. parse error) when
given a `NumericLiteral` with a negative value.

See https://codesandbox.io/p/devbox/5d47fr for repro.
2025-06-02 11:43:45 -04:00
Wesley LeMahieu ee76351917 fix typo in compiler validation filename (#33345)
## Summary

While investigating the root cause of #33208, I noticed a clear typo for
one of the validation files.

## How did you test this change?

Inside `/react/compiler/packages/babel-plugin-react-compiler` I ran the
test script successfully:

<img width="415" alt="Screenshot at May 22 16-43-06"
src="https://github.com/user-attachments/assets/3fe8c5e1-37ce-4a31-b35e-7e323e57cd9d"
/>
2025-05-30 16:31:16 -07:00
mofeiZ f9ae0a4c2e [compiler][gating] Custom opt out directives (experimental option) (#33328)
Adding an experimental / unstable compiler config to enable custom
opt-out directives
2025-05-27 12:02:29 -04:00
mofeiZ 0d072884f9 [compiler] Inferred effect dependencies now include optional chains (#33326)
Inferred effect dependencies now include optional chains.

This is a temporary solution while
https://github.com/facebook/react/pull/32099 and its followups are
worked on. Ideally, we should model reactive scope dependencies in the
IR similarly to `ComputeIR` -- dependencies should be hoisted and all
references rewritten to use the hoisted dependencies.

`
---
[//]: # (BEGIN SAPLING FOOTER)
Stack created with [Sapling](https://sapling-scm.com). Best reviewed
with [ReviewStack](https://reviewstack.dev/facebook/react/pull/33326).
* __->__ #33326
* #33325
* #32286
2025-05-22 16:14:49 -04:00
mofeiZ abf9fd559d [compiler] Add reactive flag on scope dependencies (#33325)
When collecting scope dependencies, mark each dependency with `reactive:
true | false`. This prepares for later PRs
https://github.com/facebook/react/pull/33326 and
https://github.com/facebook/react/pull/32099 which rewrite scope
dependencies into instructions.

Note that some reactive objects may have non-reactive properties, but we
do not currently track this.

Technically, state[0] is reactive and state[1] is not. Currently, both
would be marked as reactive.
```js
const state = useState();
```
---
[//]: # (BEGIN SAPLING FOOTER)
Stack created with [Sapling](https://sapling-scm.com). Best reviewed
with [ReviewStack](https://reviewstack.dev/facebook/react/pull/33325).
* #33326
* __->__ #33325
* #32286
2025-05-22 16:14:05 -04:00
mofeiZ 13f20044f3 [compiler] Prepare HIRBuilder to be used by later passes (#32286)
---
[//]: # (BEGIN SAPLING FOOTER)
Stack created with [Sapling](https://sapling-scm.com). Best reviewed
with [ReviewStack](https://reviewstack.dev/facebook/react/pull/32286).
* #33326
* #33325
* __->__ #32286
2025-05-22 16:13:50 -04:00
mofeiZ 459a2c4298 [compiler][gating] Experimental directive based gating (#33149)
Adds `dynamicGating` as an experimental option for testing rollout DX at
Meta. If specified, this enables dynamic gating which matches `use memo
if(...)` directives.

#### Example usage
Input file
```js
// @dynamicGating:{"source":"myModule"}
export function MyComponent() {
  'use memo if(isEnabled)';
   return <div>...</div>;
}
```
Compiler output
```js
import {isEnabled} from 'myModule';
export const MyComponent = isEnabled()
  ? <optimized version>
  : <original version>;
```
---
[//]: # (BEGIN SAPLING FOOTER)
Stack created with [Sapling](https://sapling-scm.com). Best reviewed
with [ReviewStack](https://reviewstack.dev/facebook/react/pull/33149).
* __->__ #33149
* #33148
2025-05-21 17:23:29 -04:00
Jan Kassens d38c7e10d3 Remove leftover Rust script (#33314)
For now we removed Rust from the codebase, remove this leftover script.

Also remove some dupes and Rust related files from `.gitignore`.
2025-05-20 12:20:51 -04:00
Joseph Savona c6c2a52ad8 [compiler] Fix error message for custom hooks (#33310)
We were printing "Custom" instead of "hook".
2025-05-19 15:29:58 -07:00
lauren 203df2c940 [compiler] Update changelog for 19.1.0-rc.2 (#33207)
Update the changelog.
2025-05-15 10:34:11 -04:00
Jan Kassens d85f86cf01 Delete stray file (#33199)
Not sure where this was coming from.
2025-05-14 11:27:36 -04:00
mofeiZ 3820740a7f [compiler][entrypoint] Fix edgecases for noEmit and opt-outs (#33148)
Title
---
[//]: # (BEGIN SAPLING FOOTER)
Stack created with [Sapling](https://sapling-scm.com). Best reviewed
with [ReviewStack](https://reviewstack.dev/facebook/react/pull/33148).
* #33149
* __->__ #33148
2025-05-09 13:37:49 -04:00
mofeiZ 5069e18060 [compiler][be] Make program traversal more readable (#33147)
React Compiler's program traversal logic is pretty lengthy and complex
as we've added a lot of features piecemeal. `compileProgram` is 300+
lines long and has confusing control flow (defining helpers inline,
invoking visitors, mutating-asts-while-iterating, mutating global
`ALREADY_COMPILED` state).

- Moved more stuff to `ProgramContext`
- Separated `compileProgram` into a bunch of helpers

Tested by syncing this stack to a Meta codebase and observing no
compilation output changes (D74487851, P1806855669, P1806855379)
---
[//]: # (BEGIN SAPLING FOOTER)
Stack created with [Sapling](https://sapling-scm.com). Best reviewed
with [ReviewStack](https://reviewstack.dev/facebook/react/pull/33147).
* #33149
* #33148
* __->__ #33147
2025-05-09 13:23:08 -04:00
Niklas Mollenhauer ac06829246 feat(compiler): Implement constant propagation for template literals (#33139)
New take on #29716

## Summary
Template literals consisting entirely of constant values will be inlined
to a string literal, effectively replacing the backticks with a double
quote.

This is done primarily to make the resulting instruction a string
literal, so it can be processed further in constant propatation. So this
is now correctly simplified to `true`:
```js
`` === "" // now true
`a${1}` === "a1" // now true
```

If a template string literal can only partially be comptime-evaluated,
it is not that useful for dead code elimination or further constant
folding steps and thus, is left as-is in that case. Same is true if the
literal contains an array, object, symbol or function.

## How did you test this change?

See added tests.
2025-05-08 09:24:22 -07:00
mofeiZ 38ef6550a8 [compiler][playground][tests] Standardize more pragmas (#33146)
(Almost) all pragmas are now one of the following:
- `@...TestOnly`: custom pragma for test fixtures
- `@<configName>` | `@<configName>:true`: enables with either true or a
default enabled value
- `@<configName>:<json value>`
2025-05-08 11:26:53 -04:00
mofeiZ b629a865fb [compiler][be] Move test pragma to separate file (#33145)
`Environment.ts` is getting complex so let's separate test / playground
parsing logic from it
---
[//]: # (BEGIN SAPLING FOOTER)
Stack created with [Sapling](https://sapling-scm.com). Best reviewed
with [ReviewStack](https://reviewstack.dev/facebook/react/pull/33145).
* #33146
* __->__ #33145
2025-05-08 11:24:44 -04:00
mofeiZ fbe7bc21b9 [compiler][be] repro edge cases for noEmit and module opt-outs (#33144)
see test fixtures
---
[//]: # (BEGIN SAPLING FOOTER)
Stack created with [Sapling](https://sapling-scm.com). Best reviewed
with [ReviewStack](https://reviewstack.dev/facebook/react/pull/33144).
* #33146
* #33145
* __->__ #33144
2025-05-08 11:18:16 -04:00
Niklas Mollenhauer 946da518eb feat(compiler): implement constant folding for unary minus (#33140)
## Summary
`-constant` is represented as a `UnaryExpression` node that is currently
not part of constant folding. If the operand is a constant number, the
node is folded to `constant * -1`. This also coerces `-0` to `0`,
resulting in `0 === -0` being folded to `true`.

## How did you test this change?
See attached tests
2025-05-07 10:15:11 -07:00
Jorge Cabiedes 7a2c7045ae [mcp] Add proper web-vitals metric collection (#33109)
Multiple things here:
- Improve the mean calculation for metrics so we don't report 0 when
web-vitals fail to be retrieved
- improve ui chaos monkey to use puppeteer APIs since only those trigger
INP/CLS metrics since we need emulated mouse clicks
- Add logic to navigate to a temp page after render since some
web-vitals metrics are only calculated when the page is backgrounded
- Some readability improvements
2025-05-06 08:50:40 -07:00
mofeiZ c129c2424b [compiler][repro] Nested fbt test fixture (#32779)
Ideally we should detect and bail out on this case to avoid babel build
failures.
2025-05-05 11:52:45 -04:00
mofeiZ 0c1575cee8 [compiler][bugfix] Bail out when a memo block declares hoisted fns (#32765)
Note that bailing out adds false positives for hoisted functions whose
only references are within other functions. For example, this rewrite
would be safe.
```js
// source program
  function foo() {
    return bar();
  }
  function bar() {
    return 42;
  }

// compiler output
let bar;
if (/* deps changed */) {
  function foo() {
    return bar();
  }
  bar = function bar() {
    return 42;
  }
}
```
These false positives are difficult to detect because any maybe-call of
foo before the definition of bar would be invalid.

Instead of bailing out, we should rewrite hoisted function declarations
to the following form.
```js
let bar$0;
if (/* deps changed */) {
  // All references within the declaring memo block
  // or before the function declaration should use
  // the original identifier `bar`
  function foo() {
    return bar();
  }
  function bar() {
    return 42;
  }
  bar$0 = bar;
}
// All references after the declaring memo block
// or after the function declaration should use
// the rewritten declaration `bar$0`
```
2025-05-05 11:45:58 -04:00
Joe Savona 0db8db178c [compiler] Validate against mutable functions being frozen
This revisits a validation I built a while ago, trying to make it more strict this time to ensure that it's high-signal.

We detect function expressions which are *known* mutable — they definitely can modify a variable defined outside of the function expression itself (modulo control flow). This uses types to look for known Store and Mutate effects only, and disregards mutations of effects. Any such function passed to a location with a Freeze effect is reported as a validation error.

This is behind a flag and disabled by default. If folks agree this makes sense to revisit, i'll test out internally and we can consider enabling by default.

ghstack-source-id: 075a731444
Pull Request resolved: https://github.com/facebook/react/pull/33079
2025-05-03 09:15:32 +09:00