Commit Graph
19463 Commits
Author SHA1 Message Date
Ruslan Lesiutin 94d5b5b2bf React DevTools 4.28.3 -> 4.28.4 (#27419)
* refactor[devtools/extension]: refactored messaging logic across
different parts of the extension ([hoxyq](https://github.com/hoxyq) in
[#27417](https://github.com/facebook/react/pull/27417))
* fix[devtools/extension]: added a workaround for proxy content script
injection in firefox ([hoxyq](https://github.com/hoxyq) in
[#27375](https://github.com/facebook/react/pull/27375))
* fix[devtools/useTransition]: don't check for dispatch property when
determining if hook is stateful ([hoxyq](https://github.com/hoxyq) in
[#27365](https://github.com/facebook/react/pull/27365))
* feat[devtools/extension]: show disclaimer when page doesnt run react
and refactor react polling logic ([hoxyq](https://github.com/hoxyq) in
[#27373](https://github.com/facebook/react/pull/27373))
* feat:-Added a delete all filters action and added title to the add
filter a… ([Biki-das](https://github.com/Biki-das) in
[#27332](https://github.com/facebook/react/pull/27332))
* fix[devtools/extension]: unregister dynamically injected content
scripts instead of filtering ([hoxyq](https://github.com/hoxyq) in
[#27369](https://github.com/facebook/react/pull/27369))
* refactor[devtools/extension]: more stable element updates polling to
avoid timed out errors ([hoxyq](https://github.com/hoxyq) in
[#27357](https://github.com/facebook/react/pull/27357))
* feat[devtools/extension]: add dark theme for popup
([rakleed](https://github.com/rakleed) in
[#27330](https://github.com/facebook/react/pull/27330))
2023-09-25 13:24:52 -04:00
Sebastian Markbåge 430e712bbd [Fizz] Restrict types of keyPath when it is known (#27418)
When we render an element, we provide the newly created keypath because
that means we're never at the root.
2023-09-25 12:26:17 -04:00
Ruslan Lesiutin 09285d5a7f refactor[devtools/extension]: refactored messaging logic across different parts of the extension (#27417)
1.
https://github.com/bvaughn/react/commit/9fc04eaf3fb701cdc14f57d5aed48f3126af6c94#diff-2c5e1f5e80e74154e65b2813cf1c3638f85034530e99dae24809ab4ad70d0143
introduced a vulnerability: we listen to `'fetch-file-with-cache'` event
from `window` to fetch sources of the file, in which we want to parse
hook names. We send this event via `window`, which means any page can
also use this and manipulate the extension to perform some `fetch()`
calls. With these changes, instead of transporting message via `window`,
we have a distinct content script, which is responsible for fetching
sources. It is notified via `chrome.runtime.sendMessage` api, so it
can't be manipulated.
2. Consistent structure of messages `{source: string, payload: object}`
in different parts of the extension
3. Added some wrappers around `chrome.scripting.executeScript` API in
`packages/react-devtools-extensions/src/background/executeScript.js`,
which support custom flow for Firefox, to simulate support of
`ExecutionWorld.MAIN`.
2023-09-25 12:02:13 -04:00
Sebastian Markbåge 69728fde0a [Flight] Dedupe suspense boundaries when it has already been found earlier (#27408)
If we track a postponed SuspenseBoundary parent that we have to replay
through before it has postponed and it postpones itself later, we need
to upgrade it to a postponed replay boundary instead of adding two.
2023-09-23 12:33:48 -04:00
Sophie Alpert 7f6201889e Ship diffInCommitPhase (#27409)
Performance tests at Meta showed neutral results.
2023-09-22 20:24:42 -07:00
Sebastian Markbåge d9e00f795b Stop flowing and then abort if a stream is cancelled (#27405)
We currently abort a stream either it's explicitly told to abort (e.g.
by an abortsignal). In this case we still finish writing what we have as
well as instructions for the client about what happened so it can
trigger fallback cases and log appropriately.

We also abort a request if the stream itself cancels. E.g. if you can't
write anymore. In this case we should not write anything to the outgoing
stream since it's supposed to be closed already now. However, we should
still abort the request so that more work isn't performed and so that we
can log the reason for it to the onError callback.

We should also not do any work after aborting.

There we need to stop the "flow" of bytes - so I call stopFlowing in the
cancel case before aborting.

The tests were testing this case but we had changed the implementation
to only start flowing at initial read (pull) instead of start like we
used to. As a result, it was no longer covering this case. We have to
call reader.read() in the tests to start the flow so that we need to
cancel it.

We also were missing a final assertion on the error logs and since we
were tracking them explicitly the extra error was silenced.
2023-09-22 15:16:49 -04:00
Ruslan Lesiutin f9d75e32ba fix[devtools/extension]: added a workaround for proxy content script injection in firefox (#27375)
Changes:
1. [Firefox-only] For some reason, Firefox might try to inject
dynamically registered content script in pages like `about:blank`. I
couldn't find a way to change this behaviour, `about:` is not a valid
scheme, so we can't exclude it and `match_about_blank` flag is not
supported in `chrome.scripting.registerContentScripts`.
2. While navigating the history in Firefox, some content scripts might
not be re-injected and still be alive. To handle this, we are now
patching `window` with `__REACT_DEVTOOLS_PROXY_INJECTED__` flag, to make
sure that proxy is injected and only once. This flag is cleared on
`pagehide` event.
2023-09-22 19:36:03 +01:00
Jan Kassens 9ba1bbd656 Upgrade to Flow 0.217.0 (#27407)
Just keeping React up to date.

[Changelog](https://github.com/facebook/flow/blob/main/Changelog.md)
2023-09-22 11:40:36 -04:00
Mofei Zhang 7b58600fb9 [tests] Repros for bugs and todos 2023-09-21 22:38:40 -04:00
Mofei Zhang b9275f65bc [ez] Add TODO bailout on non-backward compatible holey arrays
--- 

(pasted from comment) 

Instead of handling holey arrays, bail out with a TODO error. 

Older versions of babel seem to have inconsistent handling of holey arrays, at 
least when paired with HermesParser. When using these versions, we should bail 
out instead of throwing a Babel validation error. 

Issue: 

The babel ast definition for array elements changed from Array<PatternLike> to 
Array<PatternLike | null>. Older versions do not expect null in the ArrayPattern 
ast and will throw a validation error during Codegen. 

- HermesParser will parse [, b] into [NodePath<null>, NodePath<Identifier>] 

- Forget will try to preserve this holey array when we codegen back to js 

(e.g. we call a babel builder function arrayPattern([null, identifier])) 

- Babel will fail with `TypeError: Property elements[0] of ArrayPattern    
expected node to be of a type ["PatternLike"] but instead got null` 

PR that changed the AST definition: 


https://github.com/babel/babel/pull/10917/files#diff-19b555d2f3904c206af406540d9df200b1e16befedb83ff39ebfcbd876f7fa8aL52-R56 

[ez] Add TODO bailout on non-backward compatible holey arrays 

--- 

(pasted from comment) 

Instead of handling holey arrays, bail out with a TODO error. 

Older versions of babel seem to have inconsistent handling of holey arrays, at 
least when paired with HermesParser. When using these versions, we should bail 
out instead of throwing a Babel validation error. 

Issue: 

The babel ast definition for array elements changed from Array<PatternLike> to 
Array<PatternLike | null>. Older versions do not expect null in the ArrayPattern 
ast and will throw a validation error during Codegen. 

- HermesParser will parse [, b] into [NodePath<null>, NodePath<Identifier>] 

- Forget will try to preserve this holey array when we codegen back to js 

(e.g. we call a babel builder function arrayPattern([null, identifier])) 

- Babel will fail with `TypeError: Property elements[0] of ArrayPattern    
expected node to be of a type ["PatternLike"] but instead got null` 

PR that changed the AST definition: 


https://github.com/babel/babel/pull/10917/files#diff-19b555d2f3904c206af406540d9df200b1e16befedb83ff39ebfcbd876f7fa8aL52-R56
2023-09-21 20:54:58 -04:00
Lauren Tan 8b679e9138 [ez] Fix prettier not formatting test fixtures in vscode
This was super annoying. Turns out we had a top level directory for old projects 
called fixtures that shared a name with our fixture directories.
2023-09-21 17:04:25 -04:00
Lauren Tan 1ce952e687 Support hoisting const variable declarations
This PR adds preliminary support for hoisting const variable declarations. We do 
this via BuildHIR when lowering top level statements in a BlockStatement, by 
first checking which bindings are in scope to be hoistable if referenced before 
they are declared. The declarations are then hoisted to their earliest point 
where they are referenced (ie the top level statement just before) as context 
variables. 

Later, prior to codegen, we restore the original source by removing the 
DeclareContexts and transforming their associated StoreContexts back. 

Support for hoisting other kinds of declarations will come in future PRs!
2023-09-21 17:00:04 -04:00
Ruslan Lesiutin 56b14477e9 fix[devtools/useTransition]: don't check for dispatch property when determining if hook is stateful (#27365)
https://github.com/facebook/react/pull/26740 introduced regression:
React DevTools doesn't record updates for `useTransition` hook. I can
add more details about things on DevTools side, if needed.

The root cause is
https://github.com/facebook/react/blob/491aec5d6113ce5bae7c10966bc38a4a8fc091a8/packages/react-reconciler/src/ReactFiberHooks.js#L2728-L2730

React DevTools expects dispatch to be present for stateful hooks that
can schedule an update -
https://github.com/facebook/react/blob/2eed1328478e8c923fcb4e6abf5efbd9e1233402/packages/react-devtools-shared/src/backend/renderer.js#L1422-L1428

With these changes, we still call dispatch in `startTransition`, but
also patch `queue` object with it, so that React DevTools can recognise
`useTransition` as stateful hook that can schedule update.

I am not sure if this is the right approach to fix this, can we
distinguish if `startTransition` was called from `useTransition` hook or
as a standalone function?
2023-09-21 21:26:20 +01:00
Andrew Clark 68ac6dbcf8 Use MurmurHash3 when native hashing function is not available (#27399) 2023-09-21 14:59:51 -04:00
Sebastian Markbåge 47fed6961f [Fizz] Simplify ReplayNode data structure (#27395)
The key is that instead of storing different tags of resumable points,
we just store if a replay node has any resumable slots and if that's at
the root `number` or if it has resumable slots by index.

This is a simpler and more compact format because we don't have to
separate the three Resume forms.

This helps deal with Postpone in fallbacks because it doesn't just
double all the cases.
2023-09-21 13:49:57 -04:00
Sophie Alpert 3c27178a2f Update tracked value after resetting radio group (#27394)
Fixes #26876, I think. Review each commit separately (all assertions
pass in main already, except the last assertInputTrackingIsClean in
"should control radio buttons").

I'm actually a little confused on two things here:
* All the isCheckedDirty assertions are true. But I don't think we set
.checked unconditionally? So how does this happen?
* https://github.com/facebook/react/issues/26876#issuecomment-1611662862
claims that
https://github.com/facebook/react/compare/d962f35ca...1f248bdd7 contains
the faulty change, but it doesn't appear to change the restoration logic
that I've touched here. (One difference outside restoration is that
updateProperties did previously set `.checked` when `nextProp !==
lastProp` whereas the new logic in updateInput is to set it when
`node.checked !== !!checked`.)

But it seems to me like we need this call here anyway, and if it fixes
it then it fixes it? I think technically speaking we probably should do
all the updateInput() calls and then all the updateValueIfChanged()
calls—in particular I think if clicking A changed the checked radio
button from B to C then the code as I have it would be incorrect, but
that also seems unlikely so idk whether to care.

cc @zhengjitf @Luk-z who did some investigation on the original issue
2023-09-20 21:57:09 -07:00
Andrew Clark 2b3d582683 useFormState: Hash the component key path for more compact output (#27397)
To support MPA-style form submissions, useFormState sends down a key
that represents the identity of the hook on the page. It's based on the
key path of the component within the React tree; for deeply nested
hooks, this keypath can become very long. We can hash the key to make it
shorter.

Adds a method called createFastHash to the Stream Config interface.
We're not using this for security or obfuscation, only to generate a
more compact key without sacrificing too much collision resistance.

- In Node.js builds, createFastHash uses the built-in crypto module.
- In Bun builds, createFastHash uses Bun.hash. See:
https://bun.sh/docs/api/hashing#bun-hash

I have not yet implemented createFastHash in the Edge, Browser, or FB
(Hermes) stream configs because those environments do not have a
built-in hashing function that meets our requirements. (We can't use the
web standard `crypto` API because those methods are async, and yielding
to the main thread is too costly to be worth it for this particular use
case.) We'll likely use a pure JS implementation in those environments;
for now, they just return the original string without hashing it. I'll
address this in separate PRs.
2023-09-20 17:13:14 -04:00
Karim Piyar Ali 1f4936660d [Fizz] Allow passing a reason to abortStream (#26992)
## Summary

Currently `ReactFizzServer.abort` allows you to pass in the a `reason`
error, which then gets passed to the `onError` handler for each task
that ends up getting aborted. This adds in the ability to pass down that
same `reason` error to `ReactDOMServerFB.abortStream` as well.

## How did you test this change?

Added a test case to ReactDOMServerFB-test.internal.js
2023-09-20 16:41:12 -04:00
Sebastian Markbåge b775564d35 [Fizz] Ensure Resumable State is Serializable (#27388)
Moves writing queues to renderState.

We shouldn't need the resource tracking's value. We just need to know if
that resource has already been emitted. We can use a Set for this. To
ensure that set is directly serializable we can just use a
dictionary-like object with no value.

See individual commits for special cases.
2023-09-20 12:21:53 -04:00
Ruslan Lesiutin 1b1dcb8a40 feat[devtools/extension]: show disclaimer when page doesnt run react and refactor react polling logic (#27373)
Changes:
1. Refactored react polling logic, now each `.eval()` call is wrapped in
Promise, so we can chain them properly.
2. When user has browser DevTools opened and React DevTools panels were
mounted, user might navigate to the page, which doesn't have React
running. Previously, we would show just blank white page, now we will
show disclaimer. Disclaimer appears after 5 failed attempts to find
React. We will also show this disclaimer if it takes too long to load
the page, but once any React instance is loaded and registered, we will
update the panels.
3. Dark theme support for this disclaimer and popups in Firefox &
Chromium-based browsers

**Important**: this is only valid for case when React DevTools panels
were already created, like when user started debugging React app and
then switched to non-React page. If user starts to debug non-React app
(by opening browser DevTools for it), we will not create these panels,
just like before.

Q: "Why do we poll to get information about react?"
A: To handle case when react is loaded after the page has been loaded,
some sandboxes for example.

| Before | After |
| --- | --- |
| <img width="1840" alt="Screenshot 2023-09-14 at 15 37 37"
src="https://github.com/facebook/react/assets/28902667/2e6ffb39-5698-461d-bfd6-be2defb41aad">
| <img width="1840" alt="Screenshot 2023-09-14 at 15 26 16"
src="https://github.com/facebook/react/assets/28902667/1c8ad2b7-0955-41c5-b8cc-d0fdb03e13ca">
|
2023-09-20 13:30:50 +01:00
a3743b2e44 feat:-Added a delete all filters action and added title to the add filter a… (#27332)
### changes

1. A small action added to delete all filters, it can be useful to
delete when someone has a bunch of them rather than clicking on them
selectively.

2.There was no title on the `add filter` button so added the same


https://github.com/facebook/react/assets/72331432/af6c0725-05b6-4f46-b8c9-8079bd933a8e



review @hoxyq

---------

Co-authored-by: BIKI DAS <bikidas@BIKIs-MacBook-Pro.local>
Co-authored-by: Ruslan Lesiutin <rdlesyutin@gmail.com>
2023-09-20 10:26:44 +01:00
Mofei Zhang 36f979d9d4 [patch] Repro and fix for duplicate import statements 2023-09-19 18:34:14 -04:00
Joe Savona 2fa04d128e Transitive mixed type, take 2
This is a redo of #1640 now that we've established the necessary infrastructure, 
most notably `Effect.ConditionallyMutate` and `noAlias` from #2103 earlier in 
this stack. We can now understand the semantics of hooks that return deeply 
readonly values composed of primitives, arrays, or objects such that any 
`.map()` or `.filter()` calls are guaranteed to be the corresponding array 
methods. That further allows us to refine, since we know that the lambdas passed 
to these calls can't alias, are conditionally mutable, etc. All in all this 
should let us memoize less in practice.
2023-09-18 16:42:25 -07:00
Joe Savona 32569d2113 noAlias support for CallExpr incl hooks
Adds `noAlias` support for CallExpression, including hooks. Note that we treat 
hook arguments as escaping by default — ie we assume that they don't just flow 
into the hook return value, but are just outright escape points equivalent to a 
return. A `noAlias` annotation on a hook definition disables both: this will 
allow us to avoid memoizing the `graphql` tag arguments to `useFragment`, for 
example.
2023-09-18 14:38:26 -07:00
Joe Savona 0810175bba More tests for noAlias
Adds another test for `noAlias` to show that if part of the receiver could 
escape that we still memoize it.
2023-09-18 14:25:12 -07:00
Joe Savona b02f5a5e0e Dont compile code w useMemoCache
Skips compilation of code that has a reference to `useMemoCache()`, as a 
last-resort to avoid double-compilation of code. This is meant as a quick way to 
unblock since we're still seeing some double compilation issues when syncing 
internally.
2023-09-18 09:46:04 -07:00
Sebastian Markbåge 2807d781a0 [Fizz] Reuse rootSegmentID as the SuspenseBoundaryID (#27387)
Originally the intension was to have React assign an ID to a user
rendered DOM node inside a `fallback` while it was loading. If there
already were an explicit `id` defined on the DOM element we would reuse
that one instead. That's why this was a DOM Config option and not just
built in to Fizz.

This became tricky since it can load late and so we'd have to transfer
it down and detect it only once it finished rendering and if there is no
DOM element it doesn't work anyway. So instead, what we do in practice
is to always use a `<template>` tag with the ID. This has the downside
of an extra useless node and shifting child CSS selectors.

Maybe we'll get around to fixing this properly but it might not be worth
it.

This PR just gets rid of the SuspenseBoundaryID concept and instead we
just use the same ID number as the root segment ID of the boundary to
refer to the boundary to simplify the implementation.

This also solves the problem that SuspenseBoundaryID isn't currently
serializable (although that's easily fixable by itself if necessary).
2023-09-18 11:56:47 -04:00
Sebastian Markbåge 925c66a647 [Fizz] Client render the nearest child or parent suspense boundary if replay errors or is aborted (#27386)
Based on #27385.

When we error or abort during replay, that doesn't actually error the
component that errored because that has already rendered. The error only
affects any child that is not yet completed. Therefore the error kind of
gets thrown at the resumable point.

The resumable point might be a hole in the replay path, in which case
throwing there errors the parent boundary just the same as if the replay
component errored. If the hole is inside a deeper Suspense boundary
though, then it's that Suspense boundary that gets client rendered. I.e.
the child boundary. We can still finish any siblings.

In the shell all resumable points are inside a boundary since we must
have finished the shell. Therefore if you error in the root, we just
simply just turn all incomplete boundaries into client renders.
2023-09-18 11:25:56 -04:00
Sebastian Markbåge df061b3966 [Fizz] Don't bail out of flushing if we still have pending root tasks (#27385)
The idea for this check is that we shouldn't flush anything before we
flush the shell. That may or may not hold true in future formats like
RN.

It is a problem for resuming because with resuming it's possible to have
root tasks that are used for resuming but the shell was already flushed
so we can have completed boundaries before the shell has fully resumed.
What matters is whether the parent has already flushed or not.

It's not technically necessary to bail early because there won't be
anything in partialBoundaries or completedBoundaries because nothing
gets added there unless the parent has already flushed.

It's not exactly slow to have to check the length of three arrays so
it's probably not a big deal.

Flush partials in an early preamble needs further consideration
regardless.
2023-09-18 11:25:21 -04:00
Joe Savona 1879fbe644 Option to not memoize non-aliased function parameters
This has been nagging at me for a _long_ time: we unnecessarily memoize function 
callbacks passed to things like Array.prototype.map, even though we know these 
functions can't escape. This PR fixes this as follows: 

* Adds a `noAlias?: boolean` flag to builtin function signatures, defaulting to 
false if not specified. 

* Adds a feature flag, `enableNoAliasOptimizations`, to gate optimizations based 
on the value of that new flag. 

* When the feature is enabled, `PruneNonEscapingScopes` now looks up the 
signature of method calls, and avoids memoizing the arguments if the signatures 
specifies `noAlias: true`. 

* Annotates Array.prototype.map and Array.prototype.filter as `noAlias`. 

This does not mean we'll never memoize arguments to Array.prototype.map, it just 
means that the argument itself won't be considered as escaping. If the function 
still escapes by some other means it will get memoized: 

``` 

function Component(props) { 

const f = () => {}; // memoized! 

const x = [].map(f); // not from here.. 

return [x, f]; // but bc it escapes here 

} 

``` 

Note: this delivers some of the wins from #1640. That PR tried to do a bunch of 
things, part of which I already landed w the introduction of 
ConditionallyMutate, which allowed us to type Array.prototype.map. This PR 
further gives us the ability to understand functions that don't alias their 
params at all. The remaining bit from #1640 is the idea of understanding that 
key hooks such as `useFragment()` return transitively readonly, transitively 
array/object/primitive values, and any `.map()` or `.filter()` calls must be on 
arrays, allowing us to optimize them. Without that extra step, we'll still have 
to memoize a lot of `array.map()` lambdas just because we aren't sure that the 
receiver is an Array. But this PR helps with some cases, and lays the groundwork 
for the rest of that PR.
2023-09-15 16:18:03 -07:00
Sebastian Markbåge a5fc797db1 [Fizz] Replay Postponed Paths (#27379)
This forks Task into ReplayTask and RenderTask.

A RenderTask is the normal mode and it has a segment to write into.

A ReplayTask doesn't have a segment to write into because that has
already been written but instead it has a ReplayState which keeps track
of the next set of paths to follow. Once we hit a "Resume" node we
convert it into a RenderTask and continue rendering from there.

We can resume at either an Element position or a Slot position. An
Element pointing to a component doesn't mean we resume that component,
it means we resume in the child position directly below that component.
Slots are slots inside arrays.

Instead of statically forking most paths, I kept using the same path and
checked for the existence of a segment or replay state dynamically at
runtime.

However, there's still quite a bit of forking here like retryRenderTask
and retryReplayTask. Even in the new forks there's a lot of duplication
like resumeSuspenseBoundary, replaySuspenseBoundary and
renderSuspenseBoundary. There's opportunity to simplify this a bit.
2023-09-15 15:24:04 -04:00
Joe Savona bde7875f20 fbt:param does not allow jsxfragment children 2023-09-15 12:10:51 -07:00
Andrew Clark 2d2f2af29b Restrict React DOM imports from Server Components (#27382)
Adds a separate entry point for the react-dom package when it's accessed
from a Server Component environment, using the "react-server" export
condition.

When you're inside a Server Component module, you won't be able to
import client-only APIs like useState. This applies to almost all React
DOM exports, except for Float ones like preload.
2023-09-15 14:53:19 -04:00
Joe Savona dc4e63e2d5 fbt:param does not allow jsxtext children
Per the title, `<fbt:param>0</fbt:param>` is invalid FBT, you must wrap the text 
in an expression container. But that's not all, `fbt:param` can only have a 
single child, which means we have to strip out the text elements that occur from 
the whitespace in the source.
2023-09-15 11:30:01 -07:00
Joe Savona e5e71dfd59 Memoize fbt children in same scope
Fixes another special-case rule of fbt that i wasn't aware of: apparently 
`<fbt:param>` elements don't have to appear as direct children of `<fbt>`, they 
can be nested, and in this case they must appear as direct children of the fbt 
and not via an identifier indirection. This PR recursively extends the scope of 
FBT operands to make this work.
2023-09-15 10:31:55 -07:00
Sathya Gunasekaran 35fb6e05e1 [hir] Refactor function lowering from lowerFunctionExpression
Split out the HIR generation bits from the lowering of the actual function. The 
lowering will get reused when we lower object methods.
2023-09-15 17:16:05 +01:00
Sathya Gunasekaran b26cc58070 [hir] Add a "type" field to ObjectProperty
This will be used to distinguish between a property and a method.
2023-09-15 17:16:05 +01:00
Sathya Gunasekaran 88f65d44a7 [hir] Refactor out LoweredFunction from FunctionExpression 2023-09-15 17:16:04 +01:00
Sathya Gunasekaran 3bda9f78c3 [hir] Introduce ObjectMethod type
This will be used to store fields representing an object method.
2023-09-15 16:28:44 +01:00
Sathya Gunasekaran 365a88a8aa [hir] Refactor out ObjectPropertyKey
The type of ObjectProperty is specific to the key, not the ObjectProperty. In 
the future, we want to add a type to represent the value of the ObjectProperty. 

This PR moves out the fields related to the key of the ObjectProperty to a 
separate type.
2023-09-15 16:08:41 +01:00
Mofei Zhang 00e9888fb8 [ez][patch] Remove calls to NodePath.hasNode
--- 

Recent commits added calls to `NodePath.hasNode`, which does not exist in babel 
v7.1.6 (internal). Forget is failing with this error. 

```js 

TypeError: handlerPath.hasNode is not a function 

at lowerStatement (.../babel-plugin-react-forget/HIR/BuildHIR.js:924:58) 

... 

```
2023-09-15 13:55:33 +01:00
Joe Savona c70e87f535 Wrap JSXElement in expr container (for JSXAttribute) 2023-09-14 21:48:04 -07:00
Joe Savona 14630c0618 Dont compile functions w multiple args (infer mode) 2023-09-14 16:22:06 -07:00
Joe Savona ca1217be6d Wrap JSXFragment in expr container for attributes
@mofeiZ noticed that some configurations of prettier don't support JSXFragment 
appearing as a JSXAttribute value, in violation of the spec. Coincidentally I 
noticed that our internal build system also fails on this as i was trying to 
roll out on more surfaces. This PR makes sure we wrap fragments in an 
expressioncontainer if they appear as jsxattribute values.
2023-09-14 16:22:05 -07:00
Joe Savona 88b1a069c0 Add examples for phi type inference
Adds test cases that would demonstrate different output if we were to update 
InferTypes to infer the types of phi identifiers when their operands have the 
same type. We currently do infer such types, but attach them to phi.type instead 
of phi.id.type, so the type doesn't effect inference. Fixing that would cause 
the output on these examples to change — however, per the discussion on #2079, 
we'd also incorrectly set the mutable ranges in some cases and cause incorrect 
compilation. 

I did a thorough review of InferReferenceEffects and can't figure out how to 
trigger the bug in our current implementation — the bug only kicks in when phi 
operands would be mutated as a store instead of a mutate, and that cannot happen 
given our currently imprecise types on phi identifiers.
2023-09-14 11:56:09 -07:00
Mofei Zhang f993f0c2a5 [pipeline] panicOnBailout -> panicThreshold; remove isDev logging
--- 

Changed `panicOnBailout: boolean` to `panicThreshold`, which has the following 
options. Note that `ALL_ERRORS` corresponds to `panicOnBailout = true` and 
`CRITICAL_ERRORS` corresponds to `panicOnBailout = false`. `NONE` is a new 
option. 

```js 

export type PanicThresholdOptions = 

// Bail out of compilation on all errors by throwing an exception. 

| "ALL_ERRORS" 

// Bail out of compilation only on critical or unrecognized errors. 

// Instead, silently skip the erroring function. 

| "CRITICAL_ERRORS" 

// Never bail out of compilation. Instead, silently skip the erroring 

// function or file. 

| "NONE"; 

``` 

Jest seems to run babel through a different pipeline than Metro and - 
(perhaps through its complex `require` interjection logic). When running jest 
tests, exceptions thrown by babel transforms will bubble up to the nearest 
exception boundary which is often the jest test itself. This may not be a useful 
signal to anyone running a jest test with Forget enabled, as the erroring code 
may be within Forget itself or a transitively required module. 

Another reason to immediately bailing out on critical errors is that we may want 
to record errors found in the rest of the file. 

--- 

I'm not convinced that this change makes sense. A counterargument is that any 
CriticalErrors *should* be reported as parse errors, regardless of the runtime 
mode. Anyhow, this would be useful long term for our static analysis scripts 
(e.g. collecting info on bailouts and compilation info e.g. # slots used for 
JSX) as we want to compile-as-much-as-possible in those.
2023-09-14 20:00:43 +01:00
Mofei Zhang b2230f62a3 [pipeline] Make logging more structured
--- 

Add types for logged events, including a `CompileSuccess` event which can help 
us record successfully compiled Forget functions and their compilation details 
(e.g. # memoSlots used).
2023-09-14 19:40:39 +01:00
Mofei Zhang 869466bb0b Revamp compilation modes
We currently have multiple flags for targeting which functions to compile, but 
they are actually mutually exclusive. This PR consolidates to a single 
`compilationMode: 'annotation' | 'infer' | 'all'` flag: 

* Annotation compiles only functions that explicitly opt-in with "use forget" 

* Infer compiles explicitly opted-in functions (via "use forget") as well as any 
known/inferred components or hooks: 

* Component declarations 

* Component or hook-like functions (same rules as the ESLint plugin but with an 
extra check for whether it uses JSX or calls a hook) 

* All compiles all top-level functions. We should get rid of this in a follow-up 
and make tests use infer mode by default, and add explicit opt-ins where 
necessary. 

In all modes, "use no forget" always takes precedence and can be used to 
opt-out. The default mode is now "infer".
2023-09-14 19:40:39 +01:00
Mofei Zhang b3730eb496 [ez][be] Make early return explicit in compileAndInsert 2023-09-14 19:40:38 +01:00
Andrew Clark d6dcad6a8b useFormState: Only emit markers if postback state is provided (#27374)
This is an optimization where useFormState will only emit extra comment
markers if a form state is passed at the root. If no state is passed, we
don't need to emit anything because none of the hooks will match.
2023-09-14 11:46:16 -04:00