Commit Graph
19463 Commits
Author SHA1 Message Date
Mofei Zhang 19cf39f50b [effects] Track return ValueKind for function signatures 2023-05-22 19:37:50 -04:00
Joe Savona d456e4a78c Memoize based on inferred return type, not signature 2023-05-22 09:20:16 -07:00
Dennis MoradkhaniandDennis Moradkhani 4b877b6c66 Updated copyright text to Copyright (c) Meta Platforms, Inc. and its … (#26830)
…affiliates.

## Summary

There were 8 different places where the copyright comment was wrong.
Rewrote from "Copyright (c) Facebook, Inc. and its affiliates." to
"Copyright (c) Meta Platforms, Inc. and its affiliates."

## How did you test this change?
No code was changed. Comment was still a comment after changes.

Co-authored-by: Dennis Moradkhani <denmo530@student.liu.se>
2023-05-19 17:52:17 -07:00
Sanket Singh 7bd330e0b0 Updated Copyright comment from Facebook to Meta (#26833)
## Summary
Changed the comment in react/packages/react
/react.shared-subset.js saying 
```
Copyright (c) Facebook, Inc. and affiliates ..
```
To 
```
Copyright (c) Meta Platforms, Inc. and affiliates ..
```
as raised in the following issues:
https://github.com/facebook/react/issues/26829

Files Changed: 
react/packages/react/react.shared-subset.js

## How did you test this change?

Tests Required: No
2023-05-19 17:51:44 -07:00
Joe Savona 4ce22ebcfe Option to assume hooks follow the rules
Adds a new feature flag which tells the compiler to assume that hooks follow the 
Rules of React. Specifically, the idea that since any hook could be wrapped in a 
giant `useMemo()` call, all arguments to hooks have to be treated as if they're 
owned by React — and therefore become immutable — and that the return value of 
the hook is immutable. 

Our default is to assume that hooks break the rules, but in practice nearly 
every component follows them.
2023-05-19 11:05:04 -07:00
Joe Savona 7e10c51532 Put optimizations in this stack behind a feature flag
Wraps all the optimizations from this stack behind a feature flag so we can 
quickly disable if there are problems when integrating.
2023-05-18 16:20:28 -07:00
Joe Savona 94e2ae5893 Dont memoize calls that produce primitive values
Teaches InferReactiveScopeVariables that calls can produce primitives that don't 
need a scope.
2023-05-18 16:05:32 -07:00
Joe Savona 5008448d74 Rename function for clarity
Cleanup now that we use this for two things
2023-05-18 15:52:51 -07:00
Joe Savona 0322e4dbd4 InferReferenceEffects uses function types for CallExpression
Updates the InferReferenceEffects logic for CallExpression to work similarly to 
MethodCall, where we take into account the function signature (if present) when 
inferring the effects and return kind.
2023-05-18 15:52:11 -07:00
Joe Savona c0a5d86902 Reorder similar cases in InferReferenceEffects
Moves the CallExpression case next to MethodCall to make it easier to compare
2023-05-18 15:52:07 -07:00
Joe Savona a325eed472 Define Boolean/Number/String globals
Defines the `Boolean`, `String`, and `Number` global functions. This will be 
useful for allowing developers to wrap statements that produce a primitive in a 
way that Forget knows about in order to optimize better.
2023-05-18 15:52:03 -07:00
Joe Savona 46417a4ed7 Fix bug with partially memoized destructuring 2023-05-18 09:25:28 -07:00
Joe Savona a933d5e307 Repro for bug with partially memoized destructuring 2023-05-18 09:25:24 -07:00
Sebastian Markbåge 5309f10285 Remove Flight Relay DOM/Native (#26828)
The bindings upstream in Relay has been removed so we don't need these
builds anymore. The idea is to revisit an FB integration of Flight but
it wouldn't use the Relay specific bindings. It's a bit unclear how it
would look but likely more like the OSS version so not worth keeping
these around.

The `dom-relay` name also included the FB specific Fizz implementation
of the streaming config so I renamed that to `dom-fb`. There's no Fizz
implementation for Native yet so I just removed `native-relay`.

We created a configurable fork for how to encode the output of Flight
and the Relay implementation encoded it as JSON objects instead of
strings/streams. The new implementation would likely be more stream-like
and just encode it directly as string/binary chunks. So I removed those
indirections so that this can just be declared inline in
ReactFlightServer/Client.
2023-05-17 20:33:25 -04:00
Joe Savona 3603ee00a6 Retain original structure of labeled blocks
Handles some edge-cases where we previously flattened away some of the structure 
of a labeled block, instead ensuring that we retain the original shape. See the 
output. 

## Test Plan 

Tested on the internal app we're focused on (w useMemo inlining enabled), it 
works fine.
2023-05-17 15:55:54 -07:00
Joe Savona 7831ac2189 Enable InlineUseMemo in playground 2023-05-17 15:55:54 -07:00
Joe Savona f0b8cfbf25 More concise output for labeled blocks 2023-05-17 15:55:53 -07:00
Joe Savona f30041b0f0 More useMemo inlining test cases
More test cases for useMemo inlining, including the problematic case we found 
internally and some similar tricky cases with labels.
2023-05-17 15:55:52 -07:00
Joe Savona 329809de81 Dramatically simplify InlineUseMemo
I realized a wayyyy simpler approach to inlining a lambda: wrap it in a labeled 
block. The transformation is roughly as follows: 

```javascript 

// Before 

const x = useMemo(() => { 

if (a) { 

return b; 

} 

return c; 

}, [a, b, c]); 

return x; 

// After 

let x; 

label: { 

if (a) { 

x = b; 

break label; 

} 

x = c; 

break label; 

} 

return x; 

``` 

The key to making this work is fixing up some edge cases in labeled blocks, 
hence the previous PRs.
2023-05-17 15:55:51 -07:00
Joe Savona 5ee23af1a6 Elide empty if alternate blocks in codegen 2023-05-17 15:55:51 -07:00
Joe Savona 84a356274a Stop shrinking HIR to preserve fallthrough nodes
This is part of a stack to fix some edge cases in inlining of useMemo closures. 
In this first step, I'm disabling `shrink()` in order to retain more information 
about the data flow. For example, 

``` 

label: if (cond) { 

break label; 

} 

return foo; 

``` 

Would previously have shrunk away the if body, making the IfTerminal.consequent 
point directly to the fallthrough block (w the return). Now we retain a separate 
block.
2023-05-17 15:55:50 -07:00
Mofei Zhang f070cab870 [snap] add memoizeJSX flag
--- 

#1603 for snap
2023-05-17 14:39:29 -04:00
Mofei Zhang 8b38651986 [snap] Add jest test capabilities to snap
- delete output files when we detect input files are deleted 

- enable test fixtures in nested directories 

- exit with error code when we detect failures 

Note that the test failure on this PR is expected and will be fixed by #1608 (or 
happy to abandon that PR and fold the changes)
2023-05-17 14:39:28 -04:00
Mofei Zhang 7ba638ef8d [tests] delete stale .expect files
--- 

Looks like we delete `.js` files but missed `.expect` files. Jest probably 
didn't catch this because the basename of the fixtures had duplicates (in 
rule-of-hooks)
2023-05-17 14:39:28 -04:00
Mofei Zhang 0b697d1903 [babel plugin] Add codegen for useRenderCounter 2023-05-17 14:39:27 -04:00
Mofei Zhang bceb786c5a [runtime] useRenderCounter
--- 

(`react-forget-runtime` package seems to be synced to -.) 

RFC: useRenderCounter hook: 

- tracks # renders (increments on render path) 

- exposes a global renderCounterRegistry (counting # renders in alive / mounted 
components) 

Next PR will modify BabelPlugin to add codegen 

```js 

// Similar to how we're currently importing `isForgetEnabled` 

import {isInstrumentForgetEnabled_Secret} from "ReactForgetFeatureFlag"; 

// ... 

function Component_uncompiled(props) { 

if (isInstrumentForgetEnabled_Secret) { 

useRenderCounter(); 

} 

// ... 

} 

function Component_forget(props) { 

if (isInstrumentForgetEnabled_Secret) { 

useRenderCounter(); 

} 

// ... 

} 

```
2023-05-17 14:39:26 -04:00
Sathya Gunasekaran dc603bb2fa [babel] Add isDev flag and put logging behind it 2023-05-17 18:38:08 +01:00
Ibrahem Mahyob d7a98a5e97 Fix strict mode badge URL (#26825)
## Summary
Closes https://github.com/facebook/react/issues/26821

[[Fix #26821]](https://github.com/facebook/react/issues/26821) Update
strict mode badge URL


Updated the URL in the strict mode badge to point to the correct React
documentation for StrictMode. The previous URL was outdated. Now, when a
component is not running in StrictMode, the badge links to
https://react.dev/reference/react/StrictMode for more information.


## How did you test this change?

I verified that the strict mode badge now correctly links to the updated
URL. Previously, it pointed to the outdated URL
(https://fb.me/devtools-strict-mode). After the update, it correctly
points to the React Dev documentation for StrictMode
(https://react.dev/reference/react/StrictMode).


_Since its my first contribution here, i have completed the CLA_
2023-05-17 13:34:34 +01:00
Ruslan Lesiutin 2468a87358 React DevTools 4.27.7 -> 4.27.8 (#26823)
Closes https://github.com/facebook/react/issues/26787,
https://github.com/facebook/react/issues/26793

Includes these changes:
* fix[devtools]: fixed duplicated backend activation with multiple
renderers ([hoxyq](https://github.com/hoxyq) in
[#26807](https://github.com/facebook/react/pull/26807))
2023-05-17 11:40:50 +01:00
Andrew Clark f8de255e94 Lower Suspense throttling heuristic to 300ms (#26803)
Now that the throttling mechanism applies more often, we've decided to
lower this a tad to ensure it's not noticeable. The idea is it should be
just large enough to prevent jank when lots of different parts of the UI
load in rapid succession, but not large enough to make the UI feel
sluggish. There's no perfect number, it's just a heuristic.
2023-05-16 15:59:15 -04:00
Andrew Clark 4bfcd02b2c Fix Suspense throttling mechanism (#26802)
The throttling mechanism for fallbacks should apply to both their
appearance _and_ disappearance.

This was mostly addressed by #26611. See that PR for additional context.

However, a flaw in the implementation is that we only update the the
timestamp used for throttling when the fallback initially appears. We
don't update it when the real content pops in. If lots of content in
separate Suspense trees loads around the same time, you can still get
jank.

The issue is fixed by updating the throttling timestamp whenever the
visibility of a fallback changes. Not just when it appears.
2023-05-16 15:03:30 -04:00
Joe Savona 2a80ba544e Move DisableJsxMemoization-test into main compiler test w pragma
I originally created a separate test for the mode with JSX memoization disabled, 
but we can merge this into the main compiler-test and enable the feature with a 
pragma.
2023-05-15 12:12:53 -07:00
mofeiZ 8bf1ec97a4 Add flag back for inlineUseMemo
Reverts #1502, but flips test flags (e.g. `inlineUseMemo` by default, unless a 
test specifies `@inlineUseMemo false`. I figured this add less thrash for test 
fixtures, but happy to just do a clean revert (or remove the pragma altogether 
and always pass `inlineUseMemo: true`)
2023-05-15 14:27:26 -04:00
Sathya Gunasekaran f57ed15a33 [Babel] Log errors to stdout, not stderr
Writing to stderr causes buck to fail compilation.. which is not we want. Let's 
log to stdout only for now.
2023-05-15 14:45:26 +01:00
Sathya Gunasekaran 41a897797d [Babel] Format errors for console logging 2023-05-15 14:45:26 +01:00
Sathya Gunasekaran 5c8195aec7 [prettier] Fix linting 2023-05-15 14:43:39 +01:00
Sophie Alpertandeps1lon 4cd7065665 Fix uSES hydration in strict mode (#26791)
Previously, we'd call and use getSnapshot on the second render resulting
in `Warning: Text content did not match. Server: "Nay!" Client: "Yay!"`
and then `Error: Text content does not match server-rendered HTML.`.

Fixes #26095. Closes #26113. Closes #25650.

---------

Co-authored-by: eps1lon <silbermann.sebastian@gmail.com>
2023-05-12 14:18:03 -07:00
Mofei Zhang dda3e61347 [test cases] Add failing / bug tests for destructuring assignment 2023-05-12 12:48:18 -04:00
Mofei Zhang fe95b5df90 [hir] add DeclareContext (2/n)
--- 

In `lower`, we now ensure that all context variables are declared by a 
`DeclareContext` instruction. `DeclareContext` always produces a `let` 
declaration, and `StoreContext` is always a reassign. There are a few reasons we 
need `DeclareContext`: 

- DeclareLocal assumes it is storing to a SSA-fied identifier (which always 
stores an immutable primitive). This does not fit context variables. 

- Without DeclareContext, we need custom logic in some passes to initialize 
identifier / context state (e.g. `MutableRange`, ValueKind, etc) for the 
`StoreContext` that declares the context. 

This PR stack models context variables as concrete identifiers (with references 
to context variables modeled by `Place` referencing the context variable 
identifier). @josephsavona pointed out that this is abusing the notion of 
Identifier/Place, as context variables are essentially interior properties of a 
ContextEnvironment. Since we are not modeling `ContextEnvironment` implicitly or 
explicitly, all inference for context variables is essentially pointer analysis.
2023-05-12 12:48:17 -04:00
Mofei Zhang 314a5cfca5 [hir] Add Load/StoreContext (1/n)
--- 

This PR adds LoadContext and StoreContext to handle reading and writing to 
context variables. 

A context variable is any variable that is declared within a Forget-compiled 
function and reassigned within a closure. Conceptually, we want to treat these 
variables as attributes of a `EnvironmentContext` variable (as most javascript 
VMs do). 

- context variables currently do not participate in type inference (i.e. we do 
not produce type equations for loads from context variables). In the future, we 
can try typing this as `Phi(assignment1Type, assignment2Type, ...)`. 

- context variables are always treated as `Effect.Mutable`. 

- context variables do not participate in SSA, or certain optimizing passes 
(e.g. dead code elimination, constant propagation, etc). 

There is some still follow ups: 

- From my understanding, we should introduce a `DeclareContext` instruction. 

- currently, declaring a context variable (without initializing it) is broken. 
This is because the declaration lowers to `DeclareLocal`, which assumes it is 
storing to a SSA-fied identifier. 

```js 

let x; 

x = 4; 

() => { x = {}; }; 

``` 

- DeclareContext will also make some initialization logic easier. In this PR, I 
added some hack-y code to handle initializing effects / mutable ranges / other 
inference state for the first StoreContext. 

- Handle or bail on stores to context variables through destructuring assignment 

- 

~~Next PR:~~ 

- ~~Change closures to track reassigned identifiers (to extend mutable range of 
primitives)~~
2023-05-12 12:17:05 -04:00
Pieter De Baets a389046a52 [react-native] Always set RN$stopSurface (#26808)
## Summary
To support incremental adoption of bridgeless logic we want to default
to using these globals whenever they're available.

## How did you test this change?
https://github.com/facebook/react-native/pull/37410
2023-05-12 16:14:45 +01:00
Ruslan Lesiutin 67a05d03e3 fix[devtools]: fixed duplicated backend activation with multiple renderers (#26807)
## Summary
Initially reported in https://github.com/facebook/react/issues/26797.
Was not able to reproduce the exact same problem, but found this case:

1. Open corresponding codepen from the issue in debug mode
2. Open components tab of the extension
3. Refresh the page

Received multiple errors:
- Warning in the Console tab: Invalid renderer id "2".
- Error in the Components tab: Uncaught Error: Cannot add node "3"
because a node with that id is already in the Store.

This problem has occurred after landing a fix in
https://github.com/facebook/react/pull/26779. Looks like Chrome is
keeping the injected scripts (the backend in this case) and we start
backend twice.
2023-05-12 14:59:53 +01:00
Joe Savona f5bdf462b2 Enable hooks validation on playground, make deguggable
Enables hooks validation in playground. Also adds a tab to show the output of 
validation (in case it passes) with the inferred post dominator tree. We can use 
this to debug the dominator in case of false negatives. 

<img width="1724" alt="Screenshot 2023-05-11 at 11 07 08 AM" 
src="https://github.com/facebook/react-forget/assets/6425824/8f7ae472-8415-4899-aedf-c8f26094ebfe">
2023-05-11 13:39:59 -06:00
Joe Savona e649bf6429 Fixtures from ESLint rule
Incorporates the fixtures from eslint-plugin-react-hooks using a script, so that 
we can easily update them in the future. For each fixture we run the compiler 
with and without hooks validation first so that we know if the fixture is 
expected to pass — we have some false positives and false negatives that i can 
work through. For example we accidentally think that `userFetch()` is a hook, 
oops. Fixtures that should pass but error, or that should error but pass, are 
marked as `todo.<name>` or `todo.error.<name>`. 

While i was here i added the ability to have fixtures in subdirectories for 
grouping purposes.
2023-05-11 13:39:58 -06:00
Mofei Zhang d1e044b81a [deps] Add DeclareLocal to ReactiveScope decls
--- 

Try to fix bug from #1589: 

> If a declaration for an immutable identifier (i.e. one that is not later 
re-assigned, since undefined is a primitive) is sandwiched between mutations, we 
currently do not record it as an output or hoist it out of the reactive scope. 

One simple fix is to add all declared (and later referenced) identifiers as 
declarations of a reactive scope. This has some undesired effects (e.g. 
additional instructions + memo cache slots), but in practice, this shouldn't be 
happening often. 

Alternatively, we could 1.) add a pass to hoist declarations, 2.) account for 
this in constant propagation, or 3.) add a bailout
2023-05-11 16:24:37 -04:00
Mofei Zhang a2169d894a [test case] Test for DeclareLocal instruction
--- 

Record incorrect output. 

If a declaration for an immutable identifier (i.e. one that is not later 
re-assigned, since `undefined` is a primitive) is sandwiched between mutations, 
we currently do not record it as an output or hoist it out of the reactive 
scope.
2023-05-11 16:24:36 -04:00
mofeiZ 77c535ce25 [snap] Make watch mode go fast(er)
While optimizing per @josephsavona's suggestions in #1592, I noticed that we 
were clearing quite a few require cache entries. 

As of this PR, `Object.keys(require.cache)` holds 

- 1258 entries total 

- 67 files compiled from Forget source code (this is what 
`ts.createWatchCompilerHost` modifies) 

- 1120 babel source files (from node_modules) 

When working on watch mode, I'm almost always making changes to Forget source or 
test fixture files. It's a bit faster to just clear those entries (assuming that 
babel has no global state we need to invalidate). 

On my computer, re-running tests in watch mode (triggered by source code 
changes) takes: 

|   |  All tests  | One test (filter) | 

|-- |--------|----------| 

| current | 4.7s  | 1.8s  | 

| this PR  |  1.8s  | 0.1s  |
2023-05-11 14:58:51 -04:00
Mofei Zhang 5e80821aa2 [effects] Allow capture-store effects in rvals
--- 

Some typed functions need to annotate callees or arguments as `Effect.Store`. 
This PR modifies alias analysis (`InferAliasForStores`) to account for this
2023-05-10 21:55:56 -04:00
Jan Kassens df12d7eac4 [www] reduce dynamic SchedulerFeatureFlags (#26617)
For these values we're not using dynamic values. We can statically
compile in the values we're running.
2023-05-10 17:26:05 -04:00
Andrew Clark 7cd98ef2bc Fix nightly job to publish to "canary" channel (#26799)
When I was renaming the next channel to canary, I updated the
`publish_preleases` workflow correctly, but I skipped over
`publish_preleases_nightly`. Oops.
2023-05-09 22:27:35 -04:00