Compare commits

...

382 Commits

Author SHA1 Message Date
Dennis 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
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
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
Sophie Alpert 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
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
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
Andrew Clark b5810163e9
Change `yarn test` to default to experimental (#26741)
The idea is that the default `yarn test` command should be the one that
includes the most bleeding edge features, because during development you
probably want as many features enabled as possible.

That used to be `www-modern` but nowadays it's `experimental` because
we've landed a bunch of async actions stuff in experimental but it isn't
yet being tested at Meta.

So this switches the default to `experimental`.
2023-05-09 21:50:14 -04:00
Jan Kassens fda1f0b902
Flow upgrade to 0.205.1 (#26796)
Just a small upgrade to keep us current and remove unused suppressions
(probably fixed by some upgrade since).

- `*` is no longer allowed and has been an alias for `any` for a while
now.
2023-05-09 10:45:50 -04:00
Jan Kassens 7ac5e9a602
Small flowconfig fixes (#26784)
- The whole project root is included by default anyway, the include
section should be redundant and just misleading.
- The generated ignore paths ignore more than intended as they didn't
escape the `.` for regex.

Test Plan:
- wait for CI
- tested the ignore pattern change with renaming files and seeing the
expected files ignored for flow
2023-05-08 12:07:48 -04:00
Andrew Clark 16d053d592
Add useFormStatus to server rendering stub (#26788)
This was an oversight when I set up the hook in #26719.
2023-05-06 20:39:08 -04:00
dan efb381bbf9
[Release Script] Print a hint where to get the token (#26783)
I always forget where to get it.
2023-05-05 20:08:14 +01:00
Samuel Susla b00e27342d
Use native scheduler if defined in global scope (#26554)
Co-authored-by: Dan Abramov <dan.abramov@gmail.com>
2023-05-05 14:01:31 +01:00
Ruslan Lesiutin 783e7fcfa3
React DevTools 4.27.6 -> 4.27.7 (#26780)
List of changes:
* DevTools: fix backend activation ([hoxyq](https://github.com/hoxyq) in
[#26779](https://github.com/facebook/react/pull/26779))
* fix[dynamic-scripts-injection]: unregister content scripts before
registration ([hoxyq](https://github.com/hoxyq) in
[#26765](https://github.com/facebook/react/pull/26765))
2023-05-04 18:22:47 +01:00
Ruslan Lesiutin 377c5175f7
DevTools: fix backend activation (#26779)
## Summary
We have a case:
1. Open components tab
2. Close Chrome / Firefox devtools window completely
3. Reopen browser devtools panel
4. Open components tab

Currently, in version 4.27.6, we cannot load the components tree.

This PR contains two changes:
- non-functional refactoring in
`react-devtools-shared/src/devtools/store.js`: removed some redundant
type castings.
- fixed backend manager logic (introduced in
https://github.com/facebook/react/pull/26615) to activate already
registered backends. Looks like frontend of devtools also depends on
`renderer-attached` event, without it component tree won't load.

## How did you test this change?
This fixes the case mentioned prior. Currently in 4.27.6 version it is
not working, we need to refresh the page to make it work.

I've tested this in several environments: chrome, firefox, standalone
with RN application.
2023-05-04 17:34:57 +01:00
Sebastian Markbåge aef7ce5547
[Flight] Progressively Enhanced Server Actions (#26774)
This automatically exposes `$$FORM_ACTIONS` on Server References coming
from Flight. So that when they're used in a form action, we can encode
the ID for the server reference as a hidden field or as part of the name
of a button.

If the Server Action is a bound function it can have complex data
associated with it. In this case this additional data is encoded as
additional form fields.

To process a POST on the server there's now a `decodeAction` helper that
can take one of these progressive posts from FormData and give you a
function that is prebound with the correct closure and FormData so that
you can just invoke it.

I updated the fixture which now has a "Server State" that gets
automatically refreshed. This also lets us visualize form fields.
There's no "Action State" here for showing error messages that are not
thrown, that's still up to user space.
2023-05-03 18:36:57 -04:00
Sebastian Markbåge c10010a6a0
[Fizz] Gracefully handle suspending in DOM configs (#26768)
E.g. if we suspend (throw a promise) in pushStartInstance today we might
have already pushed some chunks (or even child segments potentially). We
should revert back to where we were.

This doesn't usually happen because when we suspend in a component it
doesn't write anything itself, it'll always defer to som host instance
to do the writing.

There was a todo about this already but I'm not 100% sure it's always
safe when suspending. It should be safe when suspending just regularly
because it's just a noop. We might not even want "throwing a promise" in
this mechanism to be supported longer term but for now that's how a
suspend in internals.
2023-05-03 18:13:47 -04:00
Andrew Clark f533cee8cb
Add useFormStatus to Flight fixture (#26773) 2023-05-03 15:29:32 -04:00
Andrew Gadzik 2c1117a8d0
Reuse request so that a ReabableStream body does not become disturbed (#26771) 2023-05-03 15:06:10 -04:00
Sebastian Markbåge fa7a447b9c
[Fizz] Check for nullish values on ReactCustomFormAction (#26770)
Usually we don't have to do this since we only set these in the loop but
the ReactCustomFormAction props are optional so they might be undefined.

Also moved it to a general type since it's a semi-public API.
2023-05-03 14:35:26 -04:00
Andrew Clark b7972822b5
useOptimisticState -> useOptimistic (#26772)
Drop the "state". Just "useOptimistic". It's cleaner.

This is still an experimental API. May not be the final name.
2023-05-03 14:26:00 -04:00
Andrew Clark 388686f291
Add "canary" to list of allowed npm dist tags (#26767)
Forgot this allowlist existed. It's an extra safeguard, in case we mess
up the configuration somehow.
2023-05-03 12:36:34 -04:00
Ruslan Lesiutin 8a25302c66
fix[dynamic-scripts-injection]: unregister content scripts before registration (#26765)
## Summary
Fixes #26756.

DevTools is failing to inject `__REACT_DEVTOOLS_GLOBAL_HOOK__` hook in
incognito mode. This is not happening straight-forward, but if extension
is toggled on and off, the next time I try to open it I am receiving an
error that content script was already registered.

<img width="676" alt="Screenshot 2023-05-02 at 14 36 53"
src="https://user-images.githubusercontent.com/28902667/235877692-51c5d284-79d9-4b00-b62e-d25d5bb5e056.png">

- Unregistering content scripts before attempting to register them
again. We need to inject `__REACT_DEVTOOLS_GLOBAL_HOOK__` on each page,
so this should be expected behaviour.
- Fixed error logging
 
## How did you test this change?
Local build of extension for Chrome, trying the same steps, which
resulted in an error.
No regression in performance, tested on react.dev, still the same.
2023-05-03 17:27:39 +01:00
Andrew Clark 2c2476834a
Rename "next" prerelease channel to "canary" (#26761)
The "next" prerelease channel represents what will be published the next
time we do a stable release. We publish a new "next" release every day
using a timed CI workflow.

When we introduced this prerelease channel a few years ago, another name
we considered was "canary". But I proposed "next" instead to create a
greater distinction between this channel and the "experimental" channel
(which is published at the same cadence, but includes extra experimental
features), because some other projects use "canary" to refer to releases
that are more unstable than how we would use it.

The main downside of "next" is someone might mistakenly assume the name
refers to Next.js. We were aware of this risk at the time but didn't
think it would be an issue in practice.

However, colloquially, we've ended up referring to this as the "canary"
channel anyway to avoid precisely that confusion.

So after further discussion, we've agreed to rename to "canary".

This affects the label used in the version string (e.g.
`18.3.0-next-a1c2d3e4` becomes `18.3.0-canary-a1c2d3e4`) as well as the
npm dist tags used to publish the releases. For now, I've chosen to
publish the canaries using both `@canary` and `@next` dist tags, so that
downstream consumers who might depend on `@next` have time to adjust. We
can remove that later after the change has been communicated.
2023-05-03 12:10:32 -04:00
Andrew Clark fa4314841e
Remove deprecated workflow key from Circle config (#26762)
This key was only valid during the 2.0 beta period so we can remove it.
2023-05-02 14:59:36 -04:00
Samuel Susla 5dd90c5623
Use content hash for react-native builds (#26734) 2023-05-02 12:04:02 +01:00
Sebastian Markbåge 559e83aebb
[Fizz] Allow an action provide a custom set of props to use for progressive enhancement (#26749)
Stacked on top of #26735.

This allows a framework to add a `$$FORM_ACTION` property to a function.
This lets the framework return a set of props to use in place of the
function but only during SSR. Effectively, this lets you implement
progressive enhancement of form actions using some other way instead of
relying on the replay feature.

This will be used by RSC on Server References automatically by
convention in a follow up, but this mechanism can also be used by other
frameworks/libraries.
2023-05-01 16:01:14 -04:00
Sebastian Markbåge 67f4fb0213
Allow forms to skip hydration of hidden inputs (#26735)
This allows us to emit extra ephemeral data that will only be used on
server rendered forms.

First I refactored the shouldSkip functions to now just do that work
inside the canHydrate methods. This makes the Config bindings a little
less surface area but it also helps us optimize a bit since we now can
look at the code together and find shared paths.

canHydrate returns the instance if it matches, that used to just be
there to refine the type but it can also be used to just return a
different instance later that we find. If we don't find one, we'll bail
out and error regardless so no need to skip past anything.
2023-05-01 15:35:57 -04:00
Josh Story 8ea96ef84d
[Fizz] Encode external fizz runtime into chunks eagerly (#26752)
in https://github.com/facebook/react/pull/26738 we added nonce to the
ResponseState. Initially it was used in a variety of places but the
version that got merged only included it with the external fizz runtime.
This PR updates the config for the external fizz runtime so that the
nonce is encoded into the script chunks at request creation time.

The rationale is that for live-requests, streaming is more likely than
not so doing the encoding work at the start is better than during flush.
For cases such as SSG where the runtime is not required the extra
encoding is tolerable (not a live request). Bots are an interesting case
because if you want fastest TTFB you will end up requiring the runtime
but if you are withholding until the stream is done you have already
sacrificed fastest TTFB and the marginal slowdown of the extraneous
encoding is hopefully neglibible

I'm writing this so later if we learn that this tradeoff isn't worth it
we at least understand why I made the change in the first place.
2023-05-01 10:50:36 -07:00
Andrew Clark 491aec5d61
Implement experimental_useOptimisticState (#26740)
This adds an experimental hook tentatively called useOptimisticState.
(The actual name needs some bikeshedding.)

The headline feature is that you can use it to implement optimistic
updates. If you set some optimistic state during a transition/action,
the state will be automatically reverted once the transition completes.

Another feature is that the optimistic updates will be continually
rebased on top of the latest state.

It's easiest to explain with examples; we'll publish documentation as
the API gets closer to stabilizing. See tests for now.

Technically the use cases for this hook are broader than just optimistic
updates; you could use it implement any sort of "pending" state, such as
the ones exposed by useTransition and useFormStatus. But we expect
people will most often reach for this hook to implement the optimistic
update pattern; simpler cases are covered by those other hooks.
2023-05-01 13:19:20 -04:00
Dan Ott 9545e4810c
Add nonce support to bootstrap scripts and external runtime (#26738)
Adds support for nonce on `bootstrapScripts`, `bootstrapModules` and the external fizz runtime
2023-05-01 09:19:02 -07:00
Andrew Clark 86b0e91998
Gate DevTools test to fix CI (#26742)
This test started failing recently in older versions of React because
the Scheduler priority inside a microtask is Normal instead of
Immediate. This is expected because microtasks are not Scheduler tasks;
it's an implementation detail.

I gated the test to only run in v17 because it's a regression test for
legacy Suspense behavior, and the implementation details of the snapshot
changed in v18.

Test plan
---------

Using latest:

```
yarn test --build --project devtools --release-channel=experimental profilingcache
```

Using v17 (typically runs in a timed CI workflow):

```
/scripts/circleci/download_devtools_regression_build.js 17.0 --replaceBuild
yarn test --build --project devtools --release-channel=experimental --reactVersion 17.0 profilingcache
```
2023-04-29 11:14:16 -04:00
Josh Story b12bea62d9
Preinits should support a nonce option (#26744)
Currently there is no way to provide a nonce when using
`ReactDOM.preinit(..., { as: 'script' })`

This PR adds `nonce?: string` as an option

While implementing this PR I added a test to also show you can pass
`integrity`. This test isn't directly related to the nonce change.
2023-04-28 15:57:39 -07:00
Sebastian Silbermann efbd68511d
Remove unused `initialStatus` parameter from `useHostTransitionStatus` (#26743) 2023-04-28 23:18:10 +02:00
Andrew Clark 18282f881d
Fix: Update while suspended fails to interrupt (#26739)
This fixes a bug with `use` where if you update a component that's
currently suspended, React will sometimes mistake it for a render phase
update.

This happens because we don't reset `currentlyRenderingFiber` until the
suspended is unwound. And with `use`, that can happen asynchronously,
most commonly when the work loop is suspended during a transition.

The fix is to make sure `currentlyRenderingFiber` is only set when we're
in the middle of rendering, which used to be true until `use` was
introduced.

More specifically this means clearing `currentlyRenderingFiber` when
something throws and setting it again when we resume work.

In many cases, this bug will fail "gracefully" because the update is
still added to the queue; it's not dropped completely. It's also
somewhat rare because it has to be the exact same component that's
currently suspended. But it's still a bug. I wrote a regression test
that shows a sync update failing to interrupt a suspended component.
2023-04-28 15:35:14 -04:00
Andrew Clark 540bab085d
Implement experimental_useFormStatus (#26722)
This hook reads the status of its ancestor form component, if it exists.

```js
const {pending, data, action, method} = useFormStatus();
```

It can be used to implement a loading indicator, for example. You can
think of it as a shortcut for implementing a loading state with the
useTransition hook.

For now, it's only available in the experimental channel. We'll share
docs once its closer to being stable. There are additional APIs that
will ship alongside it.

Internally it's implemented using startTransition + a context object.
That's a good way to think about its behavior, but the actual
implementation details may change in the future.

Because form elements cannot be nested, the implementation in the
reconciler does not bother to keep track of multiple nested "transition
providers". So although it's implemented using generic Fiber config
methods, it does currently make some assumptions based on React DOM's
requirements.
2023-04-26 18:19:58 -04:00
Andrew Clark 6eadbe0c4a
Fix: Resolve entangled actions independently (#26726)
When there are multiple async actions at the same time, we entangle them
together because we can't be sure which action an update might be
associated with. (For this, we'd need AsyncContext.) However, if one of
the async actions fails with an error, it should only affect that
action, not all the other actions it may be entangled with.

Resolving each action independently also means they can have independent
pending state types, rather than being limited to an `isPending`
boolean. We'll use this to implement an upcoming form API.
2023-04-25 20:43:20 -04:00
Josh Story ec5e9c2a75
Fix double preload (#26729)
I found a couple scenarios where preloads were issued too aggressively

1. During SSR, if you render a new stylesheet after the preamble flushed
it will flush a preload even if the resource was already preloaded
2. During Client render, if you call `ReactDOM.preload()` it will only
check if a preload exists in the Document before inserting a new one. It
should check for an underlying resource such as a stylesheet link or
script if the preload is for a recognized asset type
2023-04-25 15:10:34 -07:00
Rubén Norte f87e97a0a6
Handle line endings correctly on Windows in build script for RN (#26727)
## Summary

We added some post-processing in the build for RN in #26616 that broke
for users on Windows due to how line endings were handled to the regular
expression to insert some directives in the docblock. This fixes that
problem, reported in #26697 as well.

## How did you test this change?

Verified files are still built correctly on Mac/Linux. Will ask for help
to test on Windows.
2023-04-25 17:26:34 +01:00
lauren 25b99efe0c
[DevTools] Add support for useMemoCache (#26696)
useMemoCache wasn't previously supported in the DevTools, so any attempt
to inspect a component using the hook would result in a
`dispatcher.useMemoCache is not a function (it is undefined)` error.
2023-04-25 09:19:25 -07:00
Andrew Clark ed545ae3d3
Turn off enableFormActions in Meta build (#26721)
This is enabled in the canary channels, but because it's relatively
untested, we'll disable it at Meta until they're ready to start trying
it out. It can change some behavior even if you don't intentionally
start using the API.

The reason it's not a dynamic flag is that it affects the external Fizz
runtime, which currently can't read flags at runtime.
2023-04-25 12:01:34 -04:00
Sebastian Markbåge bf449ee74e
Replay Client Actions After Hydration (#26716)
We used to have Event Replaying for any kind of Discrete event where
we'd track any event after hydrateRoot and before the async code/data
has loaded in to hydrate the target. However, this didn't really work
out because code inside event handlers are expected to be able to
synchronously read the state of the world at the time they're invoked.
If we replay discrete events later, the mutable state around them like
selection or form state etc. may have changed.

This limitation doesn't apply to Client Actions:

- They're expected to be async functions that themselves work
asynchronously. They're conceptually also in the "navigation" events
that happen after the "submit" events so they're already not
synchronously even before the first `await`.
- They're expected to operate mostly on the FormData as input which we
can snapshot at the time of the event.

This PR adds a bit of inline script to the Fizz runtime (or external
runtime) to track any early submit events on the page - but only if the
action URL is our placeholder `javascript:` URL. We track a queue of
these on `document.$$reactFormReplay`. Then we replay them in order as
they get hydrated and we get a handle on the Client Action function.

I add the runtime to the `bootstrapScripts` phase in Fizz which is
really technically a little too late, because on a large page, it might
take a while to get to that script even if you have displayed the form.
However, that's also true for external runtime. So there's a very short
window we might miss an event but it's good enough and better than
risking blocking display on this script.

The main thing that makes the replaying difficult to reason about is
that we can have multiple instance of React using this same queue. This
would be very usual but you could have two different Reacts SSR:ing
different parts of the tree and using around the same version. We don't
have any coordinating ids for this. We could stash something on the form
perhaps but given our current structure it's more difficult to get to
the form instance in the commit phase and a naive solution wouldn't
preserve ordering between forms.

This solution isn't 100% guaranteed to preserve ordering between
different React instances neither but should be in order within one
instance which is the common case.

The hard part is that we don't know what instance something will belong
to until it hydrates. So to solve that I keep everything in the original
queue while we wait, so that ordering is preserved until we know which
instance it'll go into. I ended up doing a bunch of clever tricks to
make this work. These could use a lot more tests than I have right now.

Another thing that's tricky is that you can update the action before
it's replayed but we actually want to invoke the old action if that
happens. So we have to extract it even if we can't invoke it right now
just so we get the one that was there during hydration.
2023-04-25 10:22:20 -04:00
Sebastian Markbåge 64d6be7122
Use require() to implement script src in tests (#26717)
We currently use rollup to make an adhoc bundle from the file system
when we're testing an import of an external file.

This doesn't follow all the interception rules that we use in jest and
in our actual builds.

This switches to just using jest require() to load these. This means
that they effectively have to load into the global document so this only
works with global document tests which is all we have now anyway.
2023-04-25 09:12:16 -04:00
Andrew Clark 919620b293
Add stub for experimental_useFormStatus (#26719)
This wires up, but does not yet implement, an experimental hook called
useFormStatus. The hook is imported from React DOM, not React, because
it represents DOM-specific state — its return type includes FormData as
one of its fields. Other renderers that implement similar methods would
use their own renderer-specific types.

The API is prefixed and only available in the experimental channel.

It can only be used from client (browser, SSR) components, not Server
Components.
2023-04-24 20:18:34 -04:00
Sebastian Markbåge 9ece58ebaa
Go through the toString path for booleanish strings and .name property (#26720)
This is consistent with what we used to do but not what we want to do.
2023-04-24 19:26:50 -04:00
Sebastian Markbåge 5e5342b100
Insert temporary input node to polyfill submitter argument in FormData (#26714)
Insert temporary input node to polyfill submitter argument in FormData.
This works for buttons too and fixes a bug where the type attribute
wasn't reset.

I also exclude the submitter if it's a function action. This ensures
that we don't include the generated "name" when the action is a server
action. Conceptually that name doesn't exist.
2023-04-24 14:18:09 -04:00
Sebastian Markbåge 9c58a0b647
Update Flight fixture to use use() instead of Promise as a child (#26715)
The Promise as a child case seems buggy. It ends up throwing the Promise
as fatal when used in Sync rendering.
2023-04-24 14:00:25 -04:00
Sophie Alpert 9ee7964302
Fix escaping in ReactDOMInput code (#26630)
JSON.stringify isn't the right thing here. Luckily this doesn't look to have any security impact.
2023-04-24 10:33:11 -07:00
Sebastian Markbåge 2fa6323818
Restore server controlled form fields to whatever they should be (#26708)
Fizz can emit whatever it wants for the SSR version of these fields when
it's a function action so they might not align with what is in the
previous props. Therefore we need to force them to update if we're
updating to a non-function where they might be relevant again.
2023-04-23 17:44:28 -04:00
Andrew Clark 7ce765ec32
Clean up enableUseHook flag (#26707)
This has been statically enabled everywhere for months.
2023-04-23 14:50:17 -04:00
Sebastian Markbåge a21d1475ff
[Flight] Fix File Upload in Node.js (#26700)
Use the Blob constructor + append with filename instead of File
constructor. Node.js doesn't expose a global File constructor but does
support it in this form.

Queue fields until we get the 'end' event from the previous file. We
rely on previous files being available by the time a field is resolved.
However, since the 'end' event in Readable is fired after two
micro-tasks, these are not resolved in order.

I use a queue of the fields while we're still waiting on files to
finish. This still doesn't resolve files and fields in order relative to
each other but that doesn't matter for our usage.
2023-04-22 01:04:24 -04:00
Josh Story 36e4cbe2e9
[Float][Flight] Flight support for Float (#26502)
Stacked on #26557 

Supporting Float methods such as ReactDOM.preload() are challenging for
flight because it does not have an easy means to convey direct
executions in other environments. Because the flight wire format is a
JSON-like serialization that is expected to be rendered it currently
only describes renderable elements. We need a way to convey a function
invocation that gets run in the context of the client environment
whether that is Fizz or Fiber.

Fiber is somewhat straightforward because the HostDispatcher is always
active and we can just have the FlightClient dispatch the serialized
directive.

Fizz is much more challenging becaue the dispatcher is always scoped but
the specific request the dispatch belongs to is not readily available.
Environments that support AsyncLocalStorage (or in the future
AsyncContext) we will use this to be able to resolve directives in Fizz
to the appropriate Request. For other environments directives will be
elided. Right now this is pragmatic and non-breaking because all
directives are opportunistic and non-critical. If this changes in the
future we will need to reconsider how widespread support for async
context tracking is.

For Flight, if AsyncLocalStorage is available Float methods can be
called before and after await points and be expected to work. If
AsyncLocalStorage is not available float methods called in the sync
phase of a component render will be captured but anything after an await
point will be a noop. If a float call is dropped in this manner a DEV
warning should help you realize your code may need to be modified.

This PR also introduces a way for resources (Fizz) and hints (Flight) to
flush even if there is not active task being worked on. This will help
when Float methods are called in between async points within a function
execution but the task is blocked on the entire function finishing.

This PR also introduces deduping of Hints in Flight using the same
resource keys used in Fizz. This will help shrink payload sizes when the
same hint is attempted to emit over and over again
2023-04-21 20:45:51 -07:00
Andrew Clark 8f42196892
Change DOM HostContext to number instead of string (#26698)
In React DOM, we use HostContext to represent the namespace of whatever
is currently rendering — SVG, Math, or HTML. Because there is a fixed
set of possible values, we can switch this to be a number instead. My
motivation is that I want to start tracking additional information in
this type, and I want to pack all of it into a single number instead of
turning it into an object. For better performance.

(In dev, the host context type is already an object that includes
additional information, but that's dev so who cares.)

Technically, before this change, the host context could be any namespace
URI string, but any value other than SVG or Math was treated the same
way. Only SVG and Math have special behavior. So in the new structure,
there are three enum values: SVG, Math, or None, which represents the
HTML namespace as well as all other possible namespaces.
2023-04-21 21:44:43 -04:00
Andrew Clark 967d46c76c
Add error boundary to Flight fixture (#26695)
Errors in form actions are now rethrown during render (#26689), so we
can handle them using an error boundary.
2023-04-21 14:23:50 -04:00
Jan Kassens 5d7ebb4b78
Allow Node.js 20 to build (#26693)
This is stable and appears to build w/o problem. I don't see why we
should disallow it.
2023-04-21 19:23:27 +01:00
Andrew Clark fd3fb8e3c5
Rethrow errors from form actions (#26689)
This is the next step toward full support for async form actions.

Errors thrown inside form actions should cause the form to re-render and
throw the error so it can be captured by an error boundary. The behavior
is the same if the `<form />` had an internal useTransition hook, which
is pretty much exactly how we implement it, too.

The first time an action is called, the form's HostComponent is
"upgraded" to become stateful, by lazily mounting a list of hooks. The
rest of the implementation for function components can be shared.

Because the error handling behavior added in this commit is just using
useTransition under-the-hood, it also handles pending states, too.
However, this pending state can't be observed until we add a new hook
for that purpose. I'll add this next.
2023-04-21 13:29:46 -04:00
Jan Kassens c57a0f68a4
Remove react-is download hack (#26692)
This was added during an upgrade to Jest 24 in
https://github.com/facebook/react/pull/15778

By now we're at Jest 29. I think if CI passes we might not need this
hack anymore.
2023-04-21 13:11:09 -04:00
Itai Mizlish c8369527ef
update broken icon link (circleCi status) (#26688)
looks better now 🚀
2023-04-20 18:28:45 -07:00
Josh Story cc93a85332
[Fiber] InvokeGuardedCallback without metaprogramming (#26569)
InvokeGuardedCallback is now implemented with the browser fork done at
error-time rather than module-load-time. Originally it also tried to
freeze the window/document references to avoid mismatches in prototype
chains when testing React in different documents however we have since
updated our tests to not do this and it was a test only feature so I
removed it.
2023-04-20 15:08:51 -07:00
Josh Story fdad813ac7
[Float][Fiber] Enable Float methods to be called outside of render (#26557)
Stacked on #26570 

Previously we restricted Float methods to only being callable while
rendering. This allowed us to make associations between calls and their
position in the DOM tree, for instance hoisting preinitialized styles
into a ShadowRoot or an iframe Document.

When considering how we are going to support Flight support in Float
however it became clear that this restriction would lead to compromises
on the implementation because the Flight client does not execute within
the context of a client render. We want to be able to disaptch Float
directives coming from Flight as soon as possible and this requires
being able to call them outside of render.

this patch modifies Float so that its methods are callable anywhere. The
main consequence of this change is Float will always use the Document
the renderer script is running within as the HoistableRoot. This means
if you preinit as style inside a component render targeting a ShadowRoot
the style will load in the ownerDocument not the ShadowRoot. Practially
speaking it means that preinit is not useful inside ShadowRoots and
iframes.

This tradeoff was deemed acceptable because these methods are
optimistic, not critical. Additionally, the other methods, preconntect,
prefetchDNS, and preload, are not impacted because they already operated
at the level of the ownerDocument and really only interface with the
Network cache layer.

I added a couple additional fixes that were necessary for getting tests
to pass that are worth considering separately.

The first commit improves the diff for `waitForThrow` so it compares
strings if possible.

The second commit makes invokeGuardedCallback not use metaprogramming
pattern and swallows any novel errors produced from trying to run the
guarded callback. Swallowing may not be the best we can do but it at
least protects React against rapid failure when something causes the
dispatchEvent to throw.
2023-04-20 14:40:25 -07:00
Josh Story e5708b3ea9
[Tests][Fizz] Better HTML parsing behavior for Fizz tests (#26570)
In anticipation of making Fiber use the document global for dispatching
Float methods that arrive from Flight I needed to update some tests that
commonly recreated the JSDOM instance after importing react.

This change updates a few tests to only create JSDOM once per test,
before importing react-dom/client.

Additionally the current act implementation for server streaming did not
adequately model streaming semantics so I rewrite the act implementation
in a way that better mirrors how a browser would parse incoming HTML.

The new act implementation does the following

1. the first time it processes meaningful streamed content it figures
out whether it is rendering into the existing document container or if
it needs to reset the document. this is based on whether the streamed
content contains tags `<html>` or `<body>` etc...
2. Once the streaming container is set it will typically continue to
stream into that container for future calls to act. The exception is if
the streaming container is the `<head>` in which case it will switch to
streaming into the body once it receives a `<body>` tag.

This means for tests that render something like a `<div>...</div>` it
will naturally stream into the default `<div id="container">...` and for
tests that render a full document the HTML will parse like a real
browser would (with some very minor edge case differences)

I also refactored the way we move nodes from buffered content into the
document and execute any scripts we find. Previously we were using
window.eval and I switched this to just setting the external script
content as script text. Additionally the nonce logic is reworked to be a
bit simpler.
2023-04-20 14:27:02 -07:00
Andrew Clark d73d7d5908
Add `alwaysThrottleRetries` flag (#26685)
This puts the change introduced by #26611 behind a flag until Meta is
able to roll it out. Disabling the flag reverts back to the old
behavior, where retries are throttled if there's still data remaining in
the tree, but not if all the data has finished loading.

The new behavior is still enabled in the public builds.
2023-04-20 14:23:22 -04:00
Ruslan Lesiutin 7f8c501f68
React DevTools 4.27.5 -> 4.27.6 (#26684)
Full list of changes:
* Use .slice() for all substring-ing
([sophiebits](https://github.com/sophiebits) in
[#26677](https://github.com/facebook/react/pull/26677))
* cleanup[devtools]: remove named hooks & profiler changed hook indices
feature flags ([hoxyq](https://github.com/hoxyq) in
[#26635](https://github.com/facebook/react/pull/26635))
* chore[devtools/release-scripts]: update messages / fixed npm view com…
([hoxyq](https://github.com/hoxyq) in
[#26660](https://github.com/facebook/react/pull/26660))
* (patch)[DevTools] bug fix: backend injection logic not working for
undocked devtools window ([mondaychen](https://github.com/mondaychen) in
[#26665](https://github.com/facebook/react/pull/26665))
* use backend manager to support multiple backends in extension
([mondaychen](https://github.com/mondaychen) in
[#26615](https://github.com/facebook/react/pull/26615))
2023-04-20 13:34:25 +01:00
Sophie Alpert 22d5942675
Add two event system cleanup TODOs (#26678)
There is so much old stuff in these files. I am weeping.
2023-04-19 18:41:46 -07:00
Sophie Alpert 767f52237c
Use .slice() for all substring-ing (#26677)
- substr is Annex B
- substring silently flips its arguments if they're in the "wrong order", which is confusing
- slice is better than sliced bread (no pun intended) and also it works the same way on Arrays so there's less to remember

---

> I'd be down to just lint and enforce a single form just for the potential compression savings by using a repeated string.

_Originally posted by @sebmarkbage in https://github.com/facebook/react/pull/26663#discussion_r1170455401_
2023-04-19 14:26:01 -07:00
Sebastian Markbåge c826dc50de
Add (Client) Functions as Form Actions (#26674)
This lets you pass a function to `<form action={...}>` or `<button
formAction={...}>` or `<input type="submit formAction={...}>`. This will
behave basically like a `javascript:` URL except not quite implemented
that way. This is a convenience for the `onSubmit={e => {
e.preventDefault(); const fromData = new FormData(e.target); ... }`
pattern.

You can still implement a custom `onSubmit` handler and if it calls
`preventDefault`, it won't invoke the action, just like it would if you
used a full page form navigation or javascript urls. It behaves just
like a navigation and we might implement it with the Navigation API in
the future.

Currently this is just a synchronous function but in a follow up this
will accept async functions, handle pending states and handle errors.

This is implemented by setting `javascript:` URLs, but these only exist
to trigger an error message if something goes wrong instead of
navigating away. Like if you called `stopPropagation` to prevent React
from handling it or if you called `form.submit()` instead of
`form.requestSubmit()` which by-passes the `submit` event. If CSP is
used to ban `javascript:` urls, those will trigger errors when these
URLs are invoked which would be a different error message but it's still
there to notify the user that something went wrong in the plumbing.

Next up is improving the SSR state with action replaying and progressive
enhancement.
2023-04-19 16:31:08 -04:00
Andrew Clark cd2b79dedd
Initial (client-only) async actions support (#26621)
Implements initial (client-only) support for async actions behind a
flag. This is an experimental feature and the design isn't completely
finalized but we're getting closer. It will be layered alongside other
features we're working on, so it may not feel complete when considered
in isolation.

The basic description is you can pass an async function to
`startTransition` and all the transition updates that are scheduled
inside that async function will be grouped together. The `isPending`
flag will be set to true immediately, and only set back to false once
the async action has completed (as well as all the updates that it
triggers).

The ideal behavior would be that all updates spawned by the async action
are automatically inferred and grouped together; however, doing this
properly requires the upcoming (stage 2) Async Context API, which is not
yet implemented by browsers. In the meantime, we will fake this by
grouping together all transition updates that occur until the async
function has terminated. This can lead to overgrouping between unrelated
actions, which is not wrong per se, just not ideal.

If the `useTransition` hook is removed from the UI before an async
action has completed — for example, if the user navigates to a new page
— subsequent transitions will no longer be grouped with together with
that action.

Another consequence of the lack of Async Context is that if you call
`setState` inside an action but after an `await`, it must be wrapped in
`startTransition` in order to be grouped properly. If we didn't require
this, then there would be no way to distinguish action updates from
urgent updates caused by user input, too. This is an unfortunate footgun
but we can likely detect the most common mistakes using a lint rule.

Once Async Context lands in browsers, we can start warning in dev if we
detect an update that hasn't been wrapped in `startTransition`. Then,
longer term, once the feature is ubiquitous, we can rely on it for real
and allow you to call `setState` without the additional wrapper.

Things that are _not_ yet implemented in this PR, but will be added as
follow ups:

- Support for non-hook form of `startTransition`
- Canceling the async action scope if the `useTransition` hook is
deleted from the UI
- Anything related to server actions
2023-04-19 13:33:11 -04:00
Jan Kassens 6d394e3d26
[actions] commit from special branches iff they exist (#26673)
This creates 2 special branches. If these special branches exist, we'll
commit build artifacts from these branches, main otherwise.
2023-04-19 12:11:40 -04:00
Sebastian Markbåge 1f248bdd71
Switching checked to null should leave the current value (#26667)
I accidentally made a behavior change in the refactor. It turns out that
when switching off `checked` to an uncontrolled component, we used to
revert to the concept of "initialChecked" which used to be stored on
state.

When there's a diff to this computed prop and the value of props.checked
is null, then we end up in a case where it sets `checked` to
`initialChecked`:


5cbe6258bc/packages/react-dom-bindings/src/client/ReactDOMInput.js (L69)

Since we never changed `initialChecked` and it's not relevant if
non-null `checked` changes value, the only way this "change" could
trigger was if we move from having `checked` to having null.

This wasn't really consistent with how `value` works, where we instead
leave the current value in place regardless. So this is a "bug fix" that
changes `checked` to be consistent with `value` and just leave the
current value in place. This case should already have a warning in it
regardless since it's going from controlled to uncontrolled.

Related to that, there was also another issue observed in
https://github.com/facebook/react/pull/26596#discussion_r1162295872 and
https://github.com/facebook/react/pull/26588

We need to atomically apply mutations on radio buttons. I fixed this by
setting the name to empty before doing mutations to value/checked/type
in updateInput, and then set the name to whatever it should be. Setting
the name is what ends up atomically applying the changes.

---------

Co-authored-by: Sophie Alpert <git@sophiebits.com>
2023-04-19 11:46:29 -04:00
Ruslan Lesiutin b90e8ebaa5
cleanup[devtools]: remove named hooks & profiler changed hook indices feature flags (#26635)
## Summary

Removing `enableNamedHooksFeature`, `enableProfilerChangedHookIndices`,
`enableProfilerComponentTree` feature flags, they are the same for all
configurations.
2023-04-19 10:05:31 +01:00
Ruslan Lesiutin a227bcd4f4
chore[devtools/release-scripts]: update messages / fixed npm view com… (#26660)
Some minor changes, observed while working on 24.7.5 release:
- Updated numeration of text instructions
- `reactjs.org` -> `react.dev`
- Fixed using `npm view` command for node 16+, `publish-release` script
currently fails if used with node 16+
2023-04-19 10:05:16 +01:00
Sophie Alpert c6db19f9cd
[Flight] Serialize Date (#26622)
This is kind of annoying because Date implements toJSON so
JSON.stringify turns it into a string before calling our replacer
function.
2023-04-18 20:52:03 -07:00
Mengdi Chen 96fd2fb726
(patch)[DevTools] bug fix: backend injection logic not working for undocked devtools window (#26665)
bugfix for #26492

This bug would cause users unable to use the devtools (component tree
empty).

The else-if logic is broken when user switch to undocked devtools mode
(separate window) because `sender.tab` would exist in that case.
<img width="314" alt="image"
src="https://user-images.githubusercontent.com/1001890/232930094-05a74445-9189-4d50-baf1-a0360b29ef7e.png">

Tested on Chrome with a local build
2023-04-18 20:39:22 -04:00
Sebastian Markbåge d8089f2cf2
[Flight Reply] Encode FormData (#26663)
Builds on top of https://github.com/facebook/react/pull/26661

This lets you pass FormData objects through the Flight Reply
serialization. It does that by prefixing each entry with the ID of the
reference and then the decoding side creates a new FormData object
containing only those fields (without the prefix).

Ideally this should be more generic. E.g. you should be able to pass
Blobs, Streams and Typed Arrays by reference inside plain objects too.
You should also be able to send Blobs and FormData in the regular Flight
serialization too so that they can go both directions. They should be
symmetrical. We'll get around to adding more of those features in the
Flight protocol as we go.

---------

Co-authored-by: Sophie Alpert <git@sophiebits.com>
2023-04-18 14:57:33 -04:00
Sophie Alpert 1b4a0daba8
Add assertions about <input> value dirty state (#26626)
Since this is an observable behavior and is hard to think about, seems
good to have tests for this.

The expected value included in each test is the behavior that existed
prior to #26546.
2023-04-18 11:03:36 -07:00
Sophie Alpert b433c379d5
Fix input tracking bug (#26627)
In
2019ddc75f,
we changed to set .defaultValue before .value on updates. In some cases,
setting .defaultValue causes .value to change, and since we only set
.value if it has the wrong value, this resulted in us not assigning to
.value, which resulted in inputValueTracking not knowing the right
value. See new test added.

My fix here is to (a) move the value setting back up first and (b)
narrowing the fix in the aforementioned PR to newly remove the value
attribute only if it defaultValue was previously present in props.

The second half is necessary because for types where the value property
and attribute are indelibly linked (hidden checkbox radio submit image
reset button, i.e. spec modes default or default/on from
https://html.spec.whatwg.org/multipage/input.html#dom-input-value-default),
we can't remove the value attribute after setting .value, because that
will undo the assignment we just did! That is, not having (b) makes all
of those types fail to handle updating props.value.

This code is incredibly hard to think about but I think this is right
(or at least, as right as the old code was) because we set .value here
only if the nextProps.value != null, and we now remove defaultValue only
if lastProps.defaultValue != null. These can't happen at the same time
because we have long warned if value and defaultValue are simultaneously
specified, and also if a component switches between controlled and
uncontrolled.

Also, it fixes the test in https://github.com/facebook/react/pull/26626.
2023-04-18 10:49:32 -07:00
Mengdi Chen d962f35cac
[DevTools] use backend manager to support multiple backends in extension (#26615)
In the extension, currently we do the following:
1. check whether there's at least one React renderer on the page
2. if yes, load the backend to the page
3. initialize the backend 

To support multiple versions of backends, we are changing it to:
1. check the versions of React renders on the page
2. load corresponding React DevTools backends that are shipped with the
extension; if they are not contained (usually prod builds of
prereleases), show a UI to allow users to load them from UI
3. initialize each of the backends

To enable this workflow, a backend will ignore React renderers that does
not match its version

This PR adds a new file "backendManager" in the extension for this
purpose.


------
I've tested it on Chrome, Edge and Firefox extensions
2023-04-18 12:02:42 -04:00
Ruslan Lesiutin 77d3b02e5c
React DevTools 4.27.4 -> 4.27.5 (#26637)
Full list of changes (not everything included in changelog):
* refactor[devtools]: copy to clipboard only on frontend side
([hoxyq](https://github.com/hoxyq) in
[#26604](https://github.com/facebook/react/pull/26604))
* Provide icon to edge devtools.
([harrygz889](https://github.com/harrygz889) in
[#26543](https://github.com/facebook/react/pull/26543))
* [BE] move shared types & constants to consolidated locations
([mondaychen](https://github.com/mondaychen) in
[#26572](https://github.com/facebook/react/pull/26572))
* remove backend dependency from the global hook
([mondaychen](https://github.com/mondaychen) in
[#26563](https://github.com/facebook/react/pull/26563))
* Replace deprecated `new-window` with
`webContents.setWindowOpenHandler()`
([Willie-Boy](https://github.com/Willie-Boy) in
[#26559](https://github.com/facebook/react/pull/26559))
* DevTools: Inline references to fiber flags
([acdlite](https://github.com/acdlite) in
[#26542](https://github.com/facebook/react/pull/26542))
* refactor[devtools]: forbid editing class instances in props
([hoxyq](https://github.com/hoxyq) in
[#26522](https://github.com/facebook/react/pull/26522))
* Move update scheduling to microtask
([acdlite](https://github.com/acdlite) in
[#26512](https://github.com/facebook/react/pull/26512))
* Remove unnecessary CIRCLE_CI_API_TOKEN checks
([mondaychen](https://github.com/mondaychen) in
[#26499](https://github.com/facebook/react/pull/26499))
* browser extension: improve script injection logic
([mondaychen](https://github.com/mondaychen) in
[#26492](https://github.com/facebook/react/pull/26492))
* [flow] make Flow suppressions explicit on the error
([kassens](https://github.com/kassens) in
[#26487](https://github.com/facebook/react/pull/26487))
2023-04-17 17:42:02 +01:00
Sebastian Markbåge b6006201b5
Add a way to create Server Reference Proxies on the client (#26632)
This lets the client bundle encode Server References without them first
being passed from an RSC payload. Like if you just import `"use server"`
from the client. A bundler could already emit these proxies to be called
on the client but the subtle difference is that those proxies couldn't
be passed back into the server by reference. They have to be registered
with React.

We don't currently implement importing `"use server"` from client
components in the reference implementation. It'd need to expand the
Webpack plugin with a loader that rewrites files with the `"use server"`
in the client bundle.

```
"use server";

export async function action() {
   ...
}
```
->
```
import {createServerReference} from "react-server-dom-webpack/client";
import {callServer} from "some-router/call-server";

export const action = createServerReference('1234#action', callServer);
```

The technique I use here is that the compiled output has to call
`createServerReference(id, callServer)` with the `$$id` and proxy
implementation. We then return a proxy function that is registered with
a WeakMap to the particular instance of the Flight Client.

This might be hard to implement because it requires emitting module
imports to a specific stateful runtime module in the compiler. A benefit
is that this ensures that this particular reference is locked to a
specific client if there are multiple - e.g. talking to different
servers.

It's fairly arbitrary whether we use a WeakMap technique (like we do on
the client) vs an `$$id` (like we do on the server). Not sure what's
best overall. The WeakMap is nice because it doesn't leak implementation
details that might be abused to consumers. We should probably pick one
and unify.
2023-04-14 23:20:35 -04:00
Sebastian Markbåge da6c23a45c
[Flight] Fallback to importing the whole module instead of encoding every name (#26624)
We currently don't just "require" a module by its module id/path. We
encode the pair of module id/path AND its export name. That's because
with module splitting, a single original module can end up in two or
more separate modules by name. Therefore the manifest files need to
encode how to require the whole module as well as how to require each
export name.

In practice, we don't currently use this because we end up forcing
Webpack to deopt and keep it together as a single module, and we don't
even have the code in the Webpack plugin to write separate values for
each export name.

The problem is with CJS we don't statically know what all the export
names will be. Since these cases will never be module split, we don't
really need to know.

This changes the Flight requires to first look for the specific name
we're loading and then if that name doesn't exist in the manifest we
fallback to looking for the `"*"` name containing the entire module and
look for the name in there at runtime.

We could probably optimize this a bit if we assume that CJS modules on
the server never get built with a name. That way we don't have to do the
failed lookup.

Additionally, since we've recently merged filepath + name into a single
string instead of two values, we now have to split those back out by
parsing the string. This is especially unfortunate for server references
since those should really not reveal what they are but be a hash or
something. The solution might just be to split them back out into two
separate fields again.

cc @shuding
2023-04-14 21:09:09 -04:00
Sophie Alpert 2bfe4b246f
[Flight] Fix style nit from #26623 (#26629)
Maybe this is faster.
https://github.com/facebook/react/pull/26623#discussion_r1167053174
2023-04-14 09:49:41 -07:00
Sophie Alpert ab2385fa38
[Flight] Serialize weird numbers (#26623) 2023-04-14 09:28:48 -07:00
Rubén Norte 39a3b72c6d
Post-process build files for React Native to add generated signature and @nolint (#26616)
## Summary

We're enabling a new mechanism to synchronize build files from `react`
to `react-native`. That new mechanism doesn't post-process files, so we
need to add that post-processing somewhere. This PR does that when
generating the files in the first place, so the generated files in the
`build` directory are ready to be committed in the `react-native`
repository directly.

This makes use of `signedsource` to avoid direct modifications of these
files in the `react-native` repository, as well as `@noformat` and
`@nolint` to prevent unactionable CI failures in that repository.

## How did you test this change?

Generated build files for `react-native` before and after this change:
```
node ./scripts/rollup/build-all-release-channels.js react-native
```

Checked new contents. Relevant changes:

```diff
diff --color -r build-before/react-native/implementations/ReactFabric-dev.fb.js build-after/react-native/implementations/ReactFabric-dev.fb.js
10c10
<  * @generated
---
>  * @generated SignedSource<<03cef14e77b8250b567dfdf3b066085e>>
diff --color -r build-before/react-native/implementations/ReactFabric-dev.js build-after/react-native/implementations/ReactFabric-dev.js
11c11
<  * @generated
---
>  * @generated SignedSource<<e39eed38a363846ca9ee9b59a225683c>>
diff --color -r build-before/react-native/implementations/ReactFabric-prod.fb.js build-after/react-native/implementations/ReactFabric-prod.fb.js
10c10
<  * @generated
---
>  * @generated SignedSource<<f65efcd6a469d5f6fef1ce647e5ec09a>>
diff --color -r build-before/react-native/implementations/ReactFabric-prod.js build-after/react-native/implementations/ReactFabric-prod.js
11c11
<  * @generated
---
>  * @generated SignedSource<<cdd582aa889b1054b2c5faf412622b18>>
diff --color -r build-before/react-native/implementations/ReactFabric-profiling.fb.js build-after/react-native/implementations/ReactFabric-profiling.fb.js
10c10
<  * @generated
---
>  * @generated SignedSource<<81e74849b24f104882bd298f062be0fa>>
diff --color -r build-before/react-native/implementations/ReactFabric-profiling.js build-after/react-native/implementations/ReactFabric-profiling.js
11c11
<  * @generated
---
>  * @generated SignedSource<<c050b7fa1453dc21ac1c5b98146210a8>>
diff --color -r build-before/react-native/implementations/ReactNativeRenderer-dev.fb.js build-after/react-native/implementations/ReactNativeRenderer-dev.fb.js
10c10
<  * @generated
---
>  * @generated SignedSource<<9c03464b489b41c06a065aeba8619263>>
diff --color -r build-before/react-native/implementations/ReactNativeRenderer-dev.js build-after/react-native/implementations/ReactNativeRenderer-dev.js
11c11
<  * @generated
---
>  * @generated SignedSource<<18b34c037544949dcf9b28f945921ba8>>
diff --color -r build-before/react-native/implementations/ReactNativeRenderer-prod.fb.js build-after/react-native/implementations/ReactNativeRenderer-prod.fb.js
10c10
<  * @generated
---
>  * @generated SignedSource<<592e9654c584d1da523378b119bd8bd7>>
diff --color -r build-before/react-native/implementations/ReactNativeRenderer-prod.js build-after/react-native/implementations/ReactNativeRenderer-prod.js
11c11
<  * @generated
---
>  * @generated SignedSource<<91c894db99e2d76f8a32708ad6ad1bde>>
diff --color -r build-before/react-native/implementations/ReactNativeRenderer-profiling.fb.js build-after/react-native/implementations/ReactNativeRenderer-profiling.fb.js
10c10
<  * @generated
---
>  * @generated SignedSource<<5ce378a9216ea747d91b208b9fd1ebd5>>
diff --color -r build-before/react-native/implementations/ReactNativeRenderer-profiling.js build-after/react-native/implementations/ReactNativeRenderer-profiling.js
11c11
<  * @generated
---
>  * @generated SignedSource<<1c7564f446ee83142976035b2884dcfd>>
diff --color -r build-before/react-native/shims/ReactFabric.js build-after/react-native/shims/ReactFabric.js
7c7
<  * @format
---
>  * @noformat
8a9,10
>  * @nolint
>  * @generated SignedSource<<cece19ddbec9f287c995721f49c68977>>
diff --color -r build-before/react-native/shims/ReactFeatureFlags.js build-after/react-native/shims/ReactFeatureFlags.js
7c7
<  * @format
---
>  * @noformat
8a9,10
>  * @nolint
>  * @generated SignedSource<<2881c8e89ef0f73f4cf6612cb518b197>>
diff --color -r build-before/react-native/shims/ReactNative.js build-after/react-native/shims/ReactNative.js
7c7
<  * @format
---
>  * @noformat
8a9,10
>  * @nolint
>  * @generated SignedSource<<0debd6e5a17dc037cb4661315a886de6>>
diff --color -r build-before/react-native/shims/ReactNativeTypes.js build-after/react-native/shims/ReactNativeTypes.js
7c7
<  * @format
---
>  * @noformat
8a9,10
>  * @nolint
>  * @generated SignedSource<<652b117c94307244bcf5e4af18928903>>
diff --color -r build-before/react-native/shims/ReactNativeViewConfigRegistry.js build-after/react-native/shims/ReactNativeViewConfigRegistry.js
7c7
<  * @format
---
>  * @noformat
8a9,10
>  * @nolint
>  * @generated SignedSource<<ce82e8957367bee7d11379ab88e3f7c5>>
diff --color -r build-before/react-native/shims/createReactNativeComponentClass.js build-after/react-native/shims/createReactNativeComponentClass.js
7c7
<  * @format
---
>  * @noformat
8a9,10
>  * @nolint
>  * @generated SignedSource<<ede54ac2fa1b9a09e234cdf098048989>>
```
2023-04-14 11:42:48 +02:00
Tianyu Yao d121c67004
Synchronously flush the transition lane scheduled in a popstate event (#26025)
<!--
  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 debug-test --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

Browsers restore state like forms and scroll position right after the
popstate event. To make sure the page work as expected on back or
forward button, we need to flush transitions scheduled in a popstate
synchronously, and only yields if it suspends.
This PR adds a new HostConfig method to check if `window.event ===
'popstate'`, and `scheduleMicrotask` if a transition is scheduled in a
`PopStateEvent`.

## How did you test this change?

yarn test
2023-04-13 15:21:19 -04:00
Samuel Susla 7b0642bb98
Remove revertRemovalOfSiblingPrerendering killswitch (#26549)
removal of sibling prerendering has been rolled out at Meta. We can
delete the flag now.
2023-04-12 21:05:17 -04:00
Andrew Clark 8256781fdf
Throttle retries even if everything has loaded (#26611)
If a Suspense fallback is shown, and the data finishes loading really
quickly after that, we throttle the content from appearing for 500ms to
reduce thrash.

This already works for successive fallback states (like if one fallback
is nested inside another) but it wasn't being applied to the final step
in the sequence: if there were no more unresolved Suspense boundaries in
the tree, the content would appear immediately.

This fixes the throttling behavior so that it applies to all renders
that are the result of suspended data being loaded. (Our internal jargon
term for this is a "retry".)
2023-04-12 20:25:32 -04:00
Andrew Clark 72c890e312
Convert more Suspense tests to use act (2/n) (#26610)
Many of our Suspense-related tests were written before the `act` API was
introduced, and use the lower level `waitFor` helpers instead. So they
are less resilient to changes in implementation details than they could
be.

This converts some of our test suite to use `act` in more places. I
found these while working on a PR to expand our fallback throttling
mechanism to include all renders that result from a promise resolving,
even if there are no more fallbacks in the tree.

I think this covers all the remaining tests that are affected.
2023-04-12 13:36:13 -04:00
Ruslan Lesiutin 21021fb0f0
refactor[devtools]: copy to clipboard only on frontend side (#26604)
Fixes https://github.com/facebook/react/issues/26500

## Summary
- No more using `clipboard-js` from the backend side, now emitting
custom `saveToClipboard` event, also adding corresponding listener in
`store.js`
- Not migrating to `navigator.clipboard` api yet, there were some issues
with using it on Chrome, will add more details to
https://github.com/facebook/react/pull/26539

## How did you test this change?
- Tested on Chrome, Firefox, Edge
- Tested on standalone electron app: seems like context menu is not
expected to work there (cannot right-click on value, the menu is not
appearing), other logic (pressing on copy icon) was not changed
2023-04-12 16:12:03 +01:00
Harry Zumwalt 5426af3d50
Provide icon to edge devtools. (#26543)
<!--
  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
Addresses #26352.

This PR explicitly passes an icon to `chrome.devtools.panels.create()`,
so that edge devtools will display the icon when in [Focus
Mode](https://learn.microsoft.com/en-us/microsoft-edge/devtools-guide-chromium/experimental-features/focus-mode).

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

## How did you test this change?
Passing test suite (`yarn test` & `yarn test --prod`)  
Passing lint (`yarn linc`)  
Passing type checks (`yarn flow`)  

**Visual Testing**

Before Changes             | After Changes
:-------------------------:|:-------------------------:

![](https://user-images.githubusercontent.com/15645169/229591145-fe99df06-e2e3-4f21-ae31-f770d584ca6c.png)
|
![](https://user-images.githubusercontent.com/15645169/229591594-26c6cbaf-f345-4367-b234-8f3c8ab3ccb1.png)
<!--
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.
-->
2023-04-11 14:42:13 -04:00
Andrew Clark f9de24a26a
Convert more Suspense tests to use `act` (#26602)
Many of our Suspense-related tests were written before the `act` API was
introduced, and use the lower level `waitFor` helpers instead. So they
are less resilient to changes in implementation details than they could
be.

This converts some of our test suite to use `act` in more places. I
found these while working on a PR to expand our fallback throttling
mechanism to include all renders that result from a promise resolving,
even if there are no more fallbacks in the tree. This isn't all the
affected tests, just some of them — I'll be sharding the changes across
multiple PRs.
2023-04-11 13:47:29 -04:00
Sebastian Markbåge 6b90976bc1
Use already extracted values instead of reading off props for controlled components (#26596)
Since `props.x` is a possibly megamorphic access, it can be slow to
access and trigger recompilation.

When we are looping over the props and pattern matching every key,
anyway, we've already done this work. We can just reuse the same value
by stashing it outside the loop in the stack.

This only makes sense for updates in diffInCommitPhase since otherwise
we don't have the full set of props in that loop.

We also have to be careful not to skip over equal values since we need
to extract them anyway.
2023-04-11 13:32:47 -04:00
Sebastian Markbåge 343a45ffa4
Remove initOption special case (#26595)
This traces back to https://github.com/facebook/react/pull/6449 and then
another before that.

I think that back then we favored the property over the attribute, and
setting the property wouldn't be enough. However, the default path for
these are now using attributes if we don't special case it. So we don't
need it.

The only difference is that we currently have a divergence for
symbol/function behavior between controlled values that use the
getToStringValue helpers which treat them as empty string, where as
everywhere else they're treated as null/missing.

Since this comes with a warning and is a weird error case, it's probably
fine to change.
2023-04-11 12:39:00 -04:00
Andrew Clark 58742c21b8
Delete unused `eventTimes` Fiber field (#26599) 2023-04-11 08:23:04 -04:00
Andrew Clark 0b931f90e8
Remove JND delay for non-transition updates (#26597)
Updates that are marked as part of a transition are allowed to block a
render from committing. Generally, other updates cannot — however,
there's one exception that's leftover from a previous iteration of our
Suspense architecture. If an update is not the result of a known urgent
event type — known as "Default" updates — then we allow it to suspend
briefly, as long as the delay is short enough that the user won't
notice. We refer to this delay as a "Just Noticable Difference" (JND)
delay. To illustrate, if the user has already waited 400ms for an update
to be reflected on the screen, the theory is that they won't notice if
you wait an additional 100ms. So React can suspend for a bit longer in
case more data comes in. The longer the user has already waited, the
longer the JND.

While we still believe this theory is sound from a UX perspective, we no
longer think the implementation complexity is worth it. The main thing
that's changed is how we handle Default updates. We used to render
Default updates concurrently (i.e. they were time sliced, and were
scheduled with postTask), but now they are blocking. Soon, they will
also be scheduled with rAF, too, which means by the end of the next rAF,
they will have either finished rendering or the main thread will be
blocked until they do. There are various motivations for this but part
of the rationale is that anything that can be made non-blocking should
be marked as a Transition, anyway, so it's not worth adding
implementation complexity to Default.

This commit removes the JND delay for Default updates. They will now
commit immediately once the render phase is complete, even if a
component suspends.
2023-04-11 00:19:49 -04:00
Sebastian Markbåge ac43bf6870
Move validation of text nesting into ReactDOMComponent (#26594)
Extract validateTextNesting from validateDOMNesting. We only need the
parent tag when validating text nodes. Then validate it in setProp.
2023-04-10 21:41:53 -04:00
Sebastian Markbåge ca41adb8c1
Diff properties in the commit phase instead of generating an update payload (#26583)
This removes the concept of `prepareUpdate()`, behind a flag.

React Native already does everything in the commit phase, but generates
a temporary update payload before applying it.

React Fabric does it both in the render phase. Now it just moves it to a
single host config.

For DOM I forked updateProperties into one that does diffing and
updating in one pass vs just applying a pre-diffed updatePayload.

There are a few downsides of this approach:

- If only "children" has changed, we end up scheduling an update to be
done in the commit phase. Since we traverse through it anyway, it's
probably not much extra.
- It does more work in the commit phase so for a large tree that is
mostly unchanged, it'll stall longer.
- It does some extra work for special cases since that work happens if
anything has changed. We no longer have a deep bailout.
- The special cases now have to each replicate the "clean up old props"
loop, leading to extra code.

The benefit is that this doesn't allocate temporary extra objects
(possibly multiple per element if the array has to resize). It's less
work overall. It also gives us an option to reuse this function for a
sync render optimization.

Another benefit is that if we do the loop in the commit phase I can do
further optimizations by reading all props that I need for special cases
in that loop instead of polymorphic reads from props. This is what I'd
like to do in future refactors that would be stacked on top of this
change.
2023-04-10 19:09:28 -04:00
Josh Story dd0619b2ee
rename $$$hostConfig to $$$config (#26593)
We have moved away from HostConfig since the name does not fully
describe the configs we customize per runtime like FlightClient,
FlightServer, Fizz, and Fiber. This commit generalizes $$$hostconfig to
$$$config
2023-04-10 15:01:04 -07:00
Josh Story b55d319559
Rename HostConfig files to FiberConfig to clarify they are configs fo… (#26592)
part of https://github.com/facebook/react/pull/26571

merging separately to improve tracking of files renames in git

Rename HostConfig files to FiberConfig to clarify they are configs for
Fiber and not Fizz/Flight. This better conforms to the naming used in
Flight and now Fizz of `ReactFlightServerConfig` and `ReactFizzConfig`
2023-04-10 14:58:44 -07:00
Josh Story ffb8eaca59
Rename ReactServerFormatConfig to ReactFizzConfig (#26591)
part of https://github.com/facebook/react/pull/26571

merging separately to improve tracking of file renames
2023-04-10 14:54:26 -07:00
Josh Story f4f873f628
Implements wiring for Flight to have it's own "HostConfig" (#26590)
Part of https://github.com/facebook/react/pull/26571

Implements wiring for Flight to have it's own "HostConfig" from Fizz.

Historically the ServerFormatConfigs were supposed to be generic enough
to be used by Fizz and Flight. However with the addition of features
like Float the configs have evolved to be more specific to the renderer.
We may want to get back to a place where there is a pure FormatConfig
which can be shared but for now we are embracing the fact that these
runtimes need very different things and DCE cannot adequately remove the
unused stuff for Fizz when pulling this dep into Flight so we are going
to fork the configs and just maintain separate ones.

At first the Flight config will be almost empty but once Float support
in Flight lands it will have a more complex implementation

Additionally this commit normalizes the component files which make up
FlightServerConfig and FlightClientConfig. Now each file that
participates starts with ReactFlightServerConfig... and
ReactFlightClientConfig...
2023-04-10 14:51:54 -07:00
Josh Story 44db16afc6
Normalize ReactFlightServerConfig and related files (#26589)
First part of https://github.com/facebook/react/pull/26571

merging separately to help with git history with a lot of file renames
2023-04-10 14:47:23 -07:00
Mengdi Chen 451736b557
[DevTools][BE] move shared types & constants to consolidated locations (#26572)
## Summary

This pull request aims to improve the maintainability of the codebase by
consolidating types and constants that are shared between the backend
and frontend. This consolidation will allow us to maintain backwards
compatibility in the frontend in the future.

To achieve this, we have moved the shared types and constants to the
following blessed files:

- react-devtools-shared/src/constants
- react-devtools-shared/src/types
- react-devtools-shared/src/backend/types
- react-devtools-shared/src/backend/NativeStyleEditor/types

Please note that the inclusion of NativeStyleEditor in this list is
temporary, and we plan to remove it once we have a better plugin system
in place.

## How did you test this change?

I have tested it by running `yarn flow dom-node`, which reports no
errors.
2023-04-10 17:07:05 -04:00
Andrew Clark fec97ecbc4
act: Move didScheduleLegacyUpdate to ensureRootIsScheduled (#26552)
`act` uses the `didScheduleLegacyUpdate` field to simulate the behavior
of batching in React <17 and below. It's a quirk leftover from a
previous implementation, not intentionally designed.

This sets `didScheduleLegacyUpdate` every time a legacy root receives an
update as opposed to only when the `executionContext` is empty. There's
no real reason to do it this way over some other way except that it's
how it used to work before #26512 and we should try our best to maintain
the existing behavior, quirks and all, since existing tests may have
come to accidentally rely on it.

This should fix some (though not all) of the internal Meta tests that
started failing after #26512 landed.

Will add a regression test before merging.
2023-04-10 14:40:18 -04:00
Sebastian Markbåge 9a9da7721e
Don't update textarea defaultValue and input checked unnecessarily (#26580)
In #26573 I changed it so that textareas get their defaultValue reset if
you don't specify one.

However, the way that was implemented, it always set it for any update
even if it hasn't changed.

We have a test for that, but that test only works if no properties
update at all so that no update was scheduled. This fixes the test so
that it updates some unrelated prop.

I also found a test for `checked` that needed a similar fix.

Interestingly, we don't do this deduping for `defaultValue` or
`defaultChecked` on inputs and there's no test for that.
2023-04-09 22:16:38 -04:00
Sebastian Markbåge e5146cb525
Refactor some controlled component stuff (#26573)
This is mainly renaming some stuff. The behavior change is
hasOwnProperty to nullish check.

I had a bigger refactor that was a dead-end but might as well land this
part and see if I can pick it up later.
2023-04-09 18:06:16 -04:00
Josh Story 657698e48d
[Tests] `waitForThrow` should diff strings (#26568)
Currently, `waitForThrow` tries to diff the expected value against the
thrown value if it doesn't match. However if the expectation is a
string, we are not diffing against the thrown message. This commit makes
it so if we are matching against message we also diff against message.
2023-04-07 14:14:08 -07:00
Mengdi Chen dd5365878d
[DevTools] remove backend dependency from the global hook (#26563)
## Summary

- #26234 is reverted and replaced with a better approach 
- introduce a new global devtools variable to decouple the global hook's
dependency on backend/console.js, and add it to react-devtools-inline
and react-devtools-standalone

With this PR, I want to introduce a new principle to hook.js: we should
always be alert when editing this file and avoid importing from other
files.
In the past, we try to inline a lot of the implementation because we use
`.toString()` to inject this function from the extension (we still have
some old comments left). Although it is no longer inlined that way, it
has became now more important to keep it clean as it is a de facto
global API people are using (9.9K files contains it on Github search as
of today).


**File size change for extension:**
Before:
379K installHook.js

After:
 21K installHook.js
363K renderer.js
2023-04-07 03:35:36 -04:00
Andrew Clark 85bb7b685b
Fix: Move `destroy` field to shared instance object (#26561)
This fixes the "double free" bug illustrated by the regression test
added in the previous commit.

The underlying issue is that `effect.destroy` field is a mutable field
but we read it during render. This is a concurrency bug — if we had a
borrow checker, it would not allow this.

It's rare in practice today because the field is updated during the
commit phase, which takes a lock on the fiber tree until all the effects
have fired. But it's still theoretically wrong because you can have
multiple Fiber copies each with their own reference to a single destroy
function, and indeed we discovered in production a scenario where this
happens via our current APIs.

In the future these types of scenarios will be much more common because
we will introduce features where effects may run concurrently with the
render phase — i.e. an imperative `hide` method that synchronously hides
a React tree and unmounts all its effects without entering the render
phase, and without interrupting a render phase that's already in
progress.

A future version of React may also be able to run the entire commit
phase concurrently with a subsequent render phase. We can't do this now
because our data structures are not fully thread safe (see: the Fiber
alternate model) but we should be able to do this in the future.

The fix I've introduced in this commit is to move the `destroy` field to
a separate object. The effect "instance" is a shared object that remains
the same for the entire lifetime of an effect. In Rust terms, a RefCell.
The field is `undefined` if the effect is unmounted, or if the effect
ran but is not stateful. We don't explicitly track whether the effect is
mounted or unmounted because that can be inferred by the hiddenness of
the fiber in the tree, i.e. whether there is a hidden Offscreen fiber
above it.

It's unfortunate that this is stored on a separate object, because it
adds more memory per effect instance, but it's conceptually sound. I
think there's likely a better data structure we could use for effects;
perhaps just one array of effect instances per fiber. But I think this
is OK for now despite the additional memory and we can follow up with
performance optimizations later.

---------

Co-authored-by: Dan Abramov <dan.abramov@gmail.com>
Co-authored-by: Rick Hanlon <rickhanlonii@gmail.com>
Co-authored-by: Jan Kassens <jan@kassens.net>
2023-04-06 12:08:05 -04:00
Willie-Boy 60cfeeebe3
[DevTools] Replace deprecated `new-window` with `webContents.setWindowOpenHandler()` (#26559)
## Summary

The electron package was recently upgraded from ^11.1.0 to ^23.1.2
(#26337). However, the WebContents `new-window` event – that is used in
the react-devtools project – was deprecated in
[v12.0.0](https://releases.electronjs.org/release/v12.0.0) and removed
in [v22.2.0](https://releases.electronjs.org/release/v22.2.0). The event
was replaced by `webContents.setWindowOpenHandler()`. This PR replaces
the `new-window` event with `webContents.setWindowOpenHandler()`.

## How did you test this change?

I created a simple electron application with similar functionality:

```
const { app, BrowserWindow, shell } = require('electron')

const createWindow = () => {
  const mainWindow = new BrowserWindow({
    width: 800,
    height: 600
  })

  mainWindow.webContents.setWindowOpenHandler(({ url }) => {
    shell.openExternal(url)
    return { action: 'deny' }
  })

  mainWindow.loadFile('index.html')
}

app.whenReady().then(() => {
  createWindow()
})
```

---------

Co-authored-by: root <root@DESKTOP-KCGHLB8.localdomain>
2023-04-06 10:02:23 -04:00
Sebastian Markbåge 9cfba0f6ec
Clean up discrete event replaying (#26558)
We no longer replay and discrete events.

I might re-add a form of this but it'll look a little different.
2023-04-05 19:38:20 -04:00
Sophie Alpert 790ebc962d
Remove no-fallthrough lint suppressions (#26553)
The lint rule already understands a normal comment. Also a bunch of
these were unnecessary.
2023-04-04 20:08:33 -07:00
Sebastian Markbåge c15579631f
Put common aliases in Map/Set instead of switch over strings (#26551)
This is a follow up to https://github.com/facebook/react/pull/26546

This is strictly a perf optimization since we know that switches over
strings aren't optimally implemented in current engines. Basically
they're a sequence of ifs.

As a result, we're better off putting the unusual cases in a Map and the
very common cases in the beginning of the switch. We might be better off
putting very common cases in explicit ifs - just in case the engine does
optimize switches to a hash table which is potentially worse.

---------

Co-authored-by: Sophie Alpert <git@sophiebits.com>
2023-04-04 18:06:09 -04:00
Mohammad Ghorbani d5fd60f7e6
Remove findInstanceBlockingEvent unused parameters (#26534)
## Summary
First three parameters of `findInstanceBlockingEvent` are unused since I
think if we remove the unused parameters it makes it easier to know that
which parameters is need by `findInstanceBlockingEvent`.

## How did you test this change?
Existing tests.
2023-04-04 12:37:14 -04:00
Sebastian Markbåge eeabb7312f
Refactor DOM Bindings Completely Off of DOMProperty Meta Programming (#26546)
There are four places we have special cases based off the DOMProperty
config:

1) DEV-only: ReactDOMUnknownPropertyHook warns for passing booleans to
non-boolean attributes. We just need a simple list of all properties
that are affected by that. We could probably move this in under setProp
instead and have it covered by that list.
2) DEV-only: Hydration. This just needs to read the value from an
attribute and compare it to what we'd expect to see if it was rendered
on the client. This could use some simplification/unification of the
code but I decided to just keep it simple and duplicated since code size
isn't an issue.
3) DOMServerFormatConfig pushAttribute: This just maps the special case
to how to emit it as a HTML attribute.
4) ReactDOMComponent setProp: This just maps the special case to how to
emit it as setAttribute or removeAttribute.

Basically we just have to remember to keep pushAttribute and setProp
aligned. There's only one long switch in prod per environment.

This just turns it all to a giant simple switch statement with string
cases. This is in theory the most optimizable since syntactically all
the information for a hash table is there. However, unfortunately we
know that most VMs don't optimize this very well and instead just turn
them into a bunch of ifs. JSC is best. We can minimize the cost by just
moving common attribute to the beginning of the list.

If we shipped this, maybe VMs will get it together to start optimizing
this case but there's a chicken and egg problem here and the game theory
reality is that we probably don't want to regress. Therefore, I intend
to do a follow up after landing this which reintroduces an object
indirection for simple property aliases. That should be enough to make
the remaining cases palatable. I'll also extract the most common
attributes to the beginning or separate ifs.

Ran attribute-behavior fixture and the table is the same.
2023-04-04 11:05:56 -04:00
Andrew Clark 0ba4d7b0d8
DevTools: Inline references to fiber flags (#26542)
We shouldn't be referencing internal fields like fiber's `flag` directly
of DevTools. It's an implementation detail. However, over the years a
few of these have snuck in. Because of how DevTools is currently
shipped, where it's expected to be backwards compatible with older
versions of React, this prevents us from refactoring those fields inside
the reconciler.

The plan we have to address this is to fix how DevTools is shipped:
DevTools will be released in lockstep with each version of React.

Until then, though, I need a temporary solution because it's blocking a
feature I'm working on. So in meantime, I'm going to have to fork the
DevTool's code based on the React version, like we already do with the
fiber TypeOfWork enum.

As a first step, I've inlined all the references to fiber flags into the
specific call sites where they are used. Eventually we'll import these
functions from the reconciler so they stay in sync, rather than
maintaining duplicate copies of the logic.
2023-04-04 11:05:33 -04:00
Jan Kassens da94e8b24a
Revert "Cleanup enableSyncDefaultUpdate flag (#26236)" (#26528)
This reverts commit b2ae9ddb3b.

While the feature flag is fully rolled out, these tests are also testing
behavior set with an unstable flag on root, which for now we want to
preserve.

Not sure if there's a better way then adding a dynamic feature flag to
the www build?
2023-04-04 10:08:14 -04:00
Rubén Norte 0700dd50bd
Implement public instances for text nodes in Fabric (#26516)
## Summary

This adds the ability to create public instances for text nodes in
Fabric. The implementation for the public instances lives in React
Native (as it does for host components after #26437). The logic here
just handles their lazy instantiation when requested via
`getPublicInstanceFromInternalInstanceHandle`, which is called by Fabric
with information coming from the shadow tree.

It's important that the creation of public instances for text nodes is
done lazily to avoid regressing memory usage when unused. Instances for
text nodes are left intact if the public instance is never accessed.

This is necessary to implement access to text nodes in React Native as
explained in
https://github.com/react-native-community/discussions-and-proposals/pull/607

## How did you test this change?

Added unit tests (also fixed a test that was only testing the logic in a
mock :S).
2023-04-04 14:43:35 +01:00
Josh Story 4a1cc2ddd0
Fix logic around attribute seralization (#26526)
There was a bug in the attribute seralization for stylesheet resources
injected by the Fizz runtime. For boolean properties the attribute value
was set to an empty string but later immediately set to a string coerced
value. This PR fixes that bug and refactors the code paths to be clearer
2023-04-03 09:34:53 -07:00
Ruslan Lesiutin b14f8da155
refactor[devtools]: forbid editing class instances in props (#26522)
## Summary
Fixes https://github.com/facebook/react/issues/24781

Restricting from editing props, which are class instances, because their
internals should be opaque.

Proposed changes:
1. Adding new data type `class_instance`: based on prototype chain of an
object we will check if its plain or not. If not, then will be marked as
`class_instance`. This should not affect `arrays`, ..., because we do
this in the end of an `object` case in `getDataType` function.

Important detail: this approach won't work for objects created with
`Object.create`, because of the custom prototype. This can also be
bypassed by manually deleting a prototype ¯\\\_(ツ)_/¯
I am not sure if there might be a better solution (which will cover all
cases) to detect if object is a class instance. Initially I was trying
to use `Object.getPrototypeOf(object) === Object.prototype`, but this
won't work for cases when we are dealing with `iframe`.


2. Objects with a type `class_instance` will be marked as unserializable
and read-only.

## Demo
`person` is a class instance, `object` is a plain object


https://user-images.githubusercontent.com/28902667/228914791-ebdc8ab0-eb5c-426d-8163-66d56b5e8790.mov
2023-04-03 11:32:17 +01:00
Hans Otto Wirtz 7329ea81c1
Fix suspense replaying forward refs (#26535)
Continuation of https://github.com/facebook/react/issues/26420

Fixes https://github.com/facebook/react/issues/26385 and
https://github.com/facebook/react/issues/26419

---------

Co-authored-by: eps1lon <silbermann.sebastian@gmail.com>
Co-authored-by: Andrew Clark <git@andrewclark.io>
2023-04-02 18:48:28 -04:00
Andrew Clark 0ae348018d
[Float] Suspend unstyled content for up to 1 minute (#26532)
We almost never want to show content before its styles have loaded. But
eventually we will give up and allow unstyled content. So this extends
the timeout to a full minute. This somewhat arbitrary — big enough that
you'd only reach it under extreme circumstances.

Note that, like regular Suspense, the app is still interactive while
we're waiting for content to load. Only the unstyled content is blocked
from appearing, not updates in general. A new update will interrupt it.

We should figure out what the browser engines do during initial page
load and consider aligning our behavior with that. It's supposed to be
render blocking by default but there may be some cases where they, too,
give up and FOUC.
2023-03-31 15:45:45 -04:00
Andrew Clark 888874673f
Allow transitions to interrupt Suspensey commits (#26531)
I originally made it so that a Suspensey commit — i.e. a commit that's
waiting for a stylesheet, image, or font to load before proceeding —
could not be interrupted by transitions. My reasoning was that Suspensey
commits always time out after a short interval, anyway, so if the
incoming update isn't urgent, it's better to wait to commit the current
frame instead of throwing it away.

I don't think this rationale was correct, for a few reasons. There are
some cases where we'll suspend for a longer duration, like stylesheets —
it's nearly always a bad idea to show content before its styles have
loaded, so we're going to be extend this timeout to be really long.

But even in the case where the timeout is shorter, like fonts, if you
get a new update, it's possible (even likely) that update will allow us
to avoid showing a fallback, like by navigating to a different page. So
we might as well try.

The behavior now matches our behavior for interrupting a suspended
render phase (i.e. `use`), which makes sense because they're not that
conceptually different.
2023-03-31 15:35:48 -04:00
Andrew Clark 09c8d25633
Move update scheduling to microtask (#26512)
When React receives new input (via `setState`, a Suspense promise
resolution, and so on), it needs to ensure there's a rendering task
associated with the update. Most of this happens
`ensureRootIsScheduled`.

If a single event contains multiple updates, we end up running the
scheduling code once per update. But this is wasteful because we really
only need to run it once, at the end of the event (or in the case of
flushSync, at the end of the scope function's execution).

So this PR moves the scheduling logic to happen in a microtask instead.
In some cases, we will force it run earlier than that, like for
`flushSync`, but since updates are batched by default, it will almost
always happen in the microtask. Even for discrete updates.

In production, this should have no observable behavior difference. In a
testing environment that uses `act`, this should also not have a
behavior difference because React will push these tasks to an internal
`act` queue.

However, tests that do not use `act` and do not simulate an actual
production environment (like an e2e test) may be affected. For example,
before this change, if a test were to call `setState` outside of `act`
and then immediately call `jest.runAllTimers()`, the update would be
synchronously applied. After this change, that will no longer work
because the rendering task (a timer, in this case) isn't scheduled until
after the microtask queue has run.

I don't expect this to be an issue in practice because most people do
not write their tests this way. They either use `act`, or they write
e2e-style tests.

The biggest exception has been... our own internal test suite. Until
recently, many of our tests were written in a way that accidentally
relied on the updates being scheduled synchronously. Over the past few
weeks, @tyao1 and I have gradually converted the test suite to use a new
set of testing helpers that are resilient to this implementation detail.

(There are also some old Relay tests that were written in the style of
React's internal test suite. Those will need to be fixed, too.)

The larger motivation behind this change, aside from a minor performance
improvement, is we intend to use this new microtask to perform
additional logic that doesn't yet exist. Like inferring the priority of
a custom event.
2023-03-31 13:04:08 -04:00
Andrew Clark 8310854ceb
Clean up enableCapturePhaseSelectiveHydrationWithoutDiscreteEventReplay (#26521)
This flag is already enabled everywhere except for www, which is blocked
by a few tests that assert on the old behavior. Once www is ready, I'll
land this.
2023-03-31 10:25:58 -04:00
Ricky ca01f359b9
Remove skipUnmountedBoundaries (#26489)
# Overview

Landing this flag internally, will test this PR in React Native before
merging.
2023-03-30 20:58:13 -04:00
Sebastian Markbåge 43a70a610d
Limit the meaning of "custom element" to not include `is` (#26524)
This PR has a bunch of surrounding refactoring. See individual commits.

The main change is that we no longer special case `typeof is ===
'string'` as a special case according to the
`enableCustomElementPropertySupport` flag.

Effectively this means that you can't use custom properties/events,
other than the ones React knows about on `<input is="my-input">`
extensions.

This is unfortunate but there's too many paths that are forked in
inconsistent ways since we fork based on tag name. I think __the
solution is to let all React elements set unknown properties/events in
the same way as this flag__ but that's a bigger change than this flag
implies.

Since `is` is not universally supported yet anyway, this doesn't seem
like a huge loss. Attributes still work.

We still support passing the `is` prop and turn that into the
appropriate createElement call.

@josepharhar
2023-03-30 18:38:50 -04:00
dan 1308e49a69
[Flight Plugin] Scan for "use client" (#26474)
## Summary

Our toy webpack plugin for Server Components is pretty broken right now
because, now that `.client.js` convention is gone, it ends up adding
every single JS file it can find (including `node_modules`) as a
potential async dependency. Instead, it should only look for files with
the `'use client'` directive.

The ideal way is to implement this by bundling the RSC graph first.
Then, we would know which `'use client'` files were actually discovered
— and so there would be no point to scanning the disk for them. That's
how Next.js bundler does it.

We're not doing that here.

This toy plugin is very simple, and I'm not planning to do heavy
lifting. I'm just bringing it up to date with the convention. The change
is that we now read every file we discover (alas), bail if it has no
`'use client'`, and parse it if it does (to verify it's actually used as
a directive). I've changed to use `acorn-loose` because it's forgiving
of JSX (and likely TypeScript/Flow). Otherwise, this wouldn't work on
uncompiled source.

## Test plan

Verified I can get our initial Server Components Demo running after this
change. Previously, it would get stuck compiling and then emit thousands
of errors.

Also confirmed the fixture still works. (It doesn’t work correctly on
the first load after dev server starts, but that’s already the case on
main so seems unrelated.)
2023-03-30 22:05:03 +01:00
Sebastian Markbåge 1a1d61fed9
Warn for ARIA typos on custom elements (#26523)
Normally we allow any attribute/property on custom elements. However
it's a shared namespace. The `aria-` namespace applies to all generic
elements which are shared with custom elements. So arguably adding
custom extensions there is a really bad idea since it can conflict with
future additions.

It's possible there is a new standard one that's polyfilled by a custom
element but the same issue applies to React in general that we might
warn for very new additions so we just have to be quick on that.

cc @josepharhar
2023-03-30 16:31:15 -04:00
Mengdi Chen 5b8cf20b38
Add Circle CI API token to request header if available (#26519)
Follow up of #26499
A Circle CI team member got back to me. It is indeed not necessary, but
they had a regression not long ago on fetching without token.

https://discuss.circleci.com/t/is-api-token-required-when-fetching-artifacts/47606/5

To mitigate the impact of this kind of issues, let's add this token to
requests' header when it's available.
2023-03-30 16:06:56 -04:00
Sebastian Markbåge 73deff0d51
Refactor DOMProperty and CSSProperty (#26513)
This is a step towards getting rid of the meta programming in
DOMProperty and CSSProperty.

This moves isAttributeNameSafe and isUnitlessNumber to a separate shared
modules.

isUnitlessNumber is now a single switch instead of meta-programming.
There is a slight behavior change here in that I hard code a specific
set of vendor-prefixed attributes instead of prefixing all the unitless
properties. I based this list on what getComputedStyle returns in
current browsers. I removed Opera prefixes because they were [removed in
Opera](https://dev.opera.com/blog/css-vendor-prefixes-in-opera-12-50-snapshots/)
itself. I included the ms ones mentioned [in the original
PR](5abcce5343).
These shouldn't really be used anymore anyway so should be pretty safe.
Worst case, they'll fallback to the other property if you specify both.

Finally I inline the mustUseProperty special cases - which are also the
only thing that uses propertyName. These are really all controlled
components and all booleans.

I'm making a small breaking change here by treating `checked` and
`selected` specially only on the `input` and `option` tags instead of
all tags. That's because those are the only DOM nodes that actually have
those properties but we used to set them as expandos instead of
attributes before. That's why one of the tests is updated to now use
`input` instead of testing an expando on a `div` which isn't a real use
case. Interestingly this also uncovered that we update checked twice for
some reason but keeping that logic for now.

Ideally `multiple` and `muted` should move into `select` and
`audio`/`video` respectively for the same reason.

No change to the attribute-behavior fixture.
2023-03-30 14:30:57 -04:00
Andrew Clark 2d51251e60
Clean up deferRenderPhaseUpdateToNextBatch (#26511)
This is a change to some undefined behavior that we though we would do
at one point but decided not to roll out. It's already disabled
everywhere, so this just deletes the branch from the implementation and
the tests.
2023-03-30 14:10:19 -04:00
Joseph Savona 0ffc7f632b
Update useMemoCache test to confirm that cache persists across errors (#26510)
## Summary

Updates the `useMemoCache()` tests to validate that the memo cache
persists when a component does a setState during render or throws during
render. Forget's compilation output follows the general pattern used in
this test and is resilient to rendering running partway and then again
with different inputs.

## How did you test this change?

`yarn test` (this is a test-only change)
2023-03-30 07:47:22 -07:00
Sebastian Markbåge 29a3be78bd
Move ReactDOMFloat to react-dom/src/ (#26514)
This is not really part of the bindings, it's more part of the package
entry points. /shared/ is not really right neither because it's more
like an isomorphic entry point and not some utility.
2023-03-29 23:39:24 -04:00
Sebastian Markbåge 4c2fc01900
Generate safe javascript url instead of throwing with disableJavaScriptURLs is on (#26507)
We currently throw an error when disableJavaScriptURLs is on and trigger
an error boundary. I kind of thought that's what would happen with CSP
or Trusted Types anyway. However, that's not what happens. Instead, in
those environments what happens is that the error is triggered when you
try to actually visit those links. So if you `preventDefault()` or
something it'll never show up and since the error just logs to the
console or to a violation logger, it's effectively a noop to users.

We can simulate the same without CSP by simply generating a different
`javascript:` url that throws instead of executing the potential attack
vector.

This still allows these to be used - at least as long as you
preventDefault before using them in practice. This might be legit for
forms. We still don't recommend using them for links-as-buttons since
it'll be possible to "Open in a New Tab" and other weird artifacts. For
links we still recommend the technique of assigning a button role etc.

It also is a little nicer when an attack actually happens because at
least it doesn't allow an attacker to trigger error boundaries and
effectively deny access to a page.
2023-03-29 23:39:02 -04:00
Andrew Clark f0aafa1a7e
Convert a few more tests to waitFor test helpers (#26509)
Continuing my journey to migrate all the Scheduler flush* methods to
async versions of the same helpers.
2023-03-29 17:02:15 -04:00
Andrew Clark 90995ef8b0
Delete "triangle" resuming fuzz tester (#26508)
This deletes the ReactIncrementalTriangle test suite, which I originally
added back in 2017 when I was working on Fiber's "resuming" feature. It
was meant to simulate a similar scenario as Seb's "Sierpinski Triangle"
Fiber demo.

We eventually ended up removing resuming, but we kept this fuzz tester
around since it wasn't really harming anything. However, over the years,
we've had to make many small tweaks to decouple it from implementation
details, to the point that it doesn't test anything useful anymore. And
the thing that it originally tested has long since been removed.

If or when we do add back resuming, we would write a different fuzz
tester from scratch rather than build on this one.

So rather than continue to contrive ways to prevent it from breaking, I
propose we delete it.

We still have other fuzz testers for things like Suspense and context
propagation. Only this particular one has outlived its usefulness.
2023-03-29 16:48:02 -04:00
Sebastian Silbermann f118b7cebf
[Flight] Gated test for dropped transport of undefined object values (#26478)
## Summary

With https://github.com/facebook/react/pull/26349 we now serialize
`undefined`. However, deserializing it on the client is currently
indistinguishable from the value missing entirely due to how
`JSON.parse` treats `undefined` return value of reviver functions.

This leads to inconsistent behavior of the `Object.hasOwn` or `in`
operator (used for narrowing in TypeScript). In TypeScript-speak, `{
prop: T | undefined}` will arrive as `{ prop?: T }`.

## How did you test this change?

- Added test that is expected to fail. Though ideally the implementation
of the component would not care whether it's used on the client or
server.
2023-03-29 18:27:55 +02:00
Sebastian Silbermann fd0511c728
[Flight] Add support BigInt support (#26479)
## Summary

Adds support for sending `BigInt` to Flight and Flight Reply

## How did you test this change?

- added tests
2023-03-29 18:23:43 +02:00
Sebastian Markbåge 85de6fde51
Refactor DOM special cases per tags including controlled fields (#26501)
I use a shared helper when setting properties into a helper whether it's
initial or update.

I moved the special cases per tag to commit phase so we can check it
only once. This also effectively inlines getHostProps which can be done
in a single check per prop key.

The diffProperties operation is simplified to mostly just generating a
plain diff of all properties, generating an update payload. This might
generate a few more entries that are now ignored in the commit phase.
that previously would've been ignored earlier. We could skip this and
just do the whole diff in the commit phase by always scheduling a commit
phase update.

I tested the attribute table (one change documented below) and a few
select DOM fixtures.
2023-03-28 22:40:03 -04:00
Mengdi Chen 5cbe6258bc
Remove unnecessary CIRCLE_CI_API_TOKEN checks (#26499)
Token is not required for GET
2023-03-28 16:31:34 -04:00
Andrew Clark 1f5cdf8c77
Update Suspense fuzz tests to use `act` (#26498)
This updates the Suspense fuzz tester to use `act` to recursively flush
timers instead of doing it manually.

This still isn't great because ideally the fuzz tester wouldn't fake
timers at all. It should resolve promises using a custom queue instead
of Jest's fake timer queue, like we've started doing in our other
Suspense tests (i.e. the `resolveText` pattern). That's because our
internal `act` API (not the public one, the one we use in our tests)
uses Jest's fake timer queue as a way to force Suspense fallbacks to
appear.

However I'm not interested in upgrading this test suite to a better
strategy right now because if I were writing a Suspense fuzzer today I
would probably use an entirely different approach. So this is just an
incremental improvement to make it slightly less decoupled to React
implementation details.
2023-03-28 14:40:28 -04:00
Ricky f62cb39ee5
Make disableSchedulerTimeoutInWorkLoop a static ff (#26497)
## Overview

There's a known infinite loop with this but we're not running an
experiment any time soon.
2023-03-28 14:11:52 -04:00
Mengdi Chen f718199313
[DevTools] browser extension: improve script injection logic (#26492)
## Summary

- Drop extension support for Chrome / Edge <v102 since they have less
than 0.1% usage ([see data](https://caniuse.com/usage-table))
- Improve script injection logic when possible so that the scripts
injected by the extension are no longer shown in Network (which caused a
lot of confusion in the past)

## How did you test this change?

Built and tested locally, works as usual on Firefox.

For Chrome/Edge

**Before:**
Scripts shown in Network tab
<img width="1279" alt="Untitled 2"
src="https://user-images.githubusercontent.com/1001890/228074363-1d00d503-d4b5-4339-8dd6-fd0467e36e3e.png">

**After:**
No scripts shown
<img width="1329" alt="image"
src="https://user-images.githubusercontent.com/1001890/228074596-2084722b-bf3c-495e-a852-15f122233155.png">

---------

Co-authored-by: Ruslan Lesiutin <rdlesyutin@gmail.com>
2023-03-28 12:45:53 -04:00
Ricky 41b4714f19
Remove disableNativeComponentFrames (#26490)
## Overview

I'm landing this flag internally so we can delete this
2023-03-28 09:46:26 -04:00
Andrew Clark fc90eb6368
Codemod more tests to waitFor pattern (#26494) 2023-03-28 00:03:57 -04:00
Andrew Clark e0bbc26623
Improve tests that deal with microtasks (#26493)
I rewrote some of our tests that deal with microtasks with the aim of
making them less coupled to implementation details. This is related to
an upcoming change to move update processing into a microtask.
2023-03-27 23:17:55 -04:00
Andrew Clark 8faf751937
Codemod some expiration tests to waitForExpired (#26491)
Continuing my journey to migrate all the Scheduler flush* methods to
async versions of the same helpers.

`unstable_flushExpired` is a rarely used helper that is only meant to be
used to test a very particular implementation detail (update starvation
prevention, or what we sometimes refer to as "expiration").

I've prefixed the new helper with `unstable_`, too, to indicate that our
tests should almost always prefer one of the other patterns instead.
2023-03-27 15:52:25 -04:00
Jan Kassens 8342a09927
Remove unused feature flag disableSchedulerTimeoutBasedOnReactExpirationTime (#26488)
Easy removal as it's completely unused as @rickhanlonii noticed.
2023-03-27 17:52:02 +02:00
Jan Kassens afea1d0c53
[flow] make Flow suppressions explicit on the error (#26487)
Added an explicit type to all $FlowFixMe suppressions to reduce
over-suppressions of new errors that might be caused on the same lines.

Also removes suppressions that aren't used (e.g. in a `@noflow` file as
they're purely misleading)

Test Plan:
yarn flow-ci
2023-03-27 13:43:04 +02:00
Andrew Clark 768f965de2
Suspensily committing a prerendered tree (#26434)
Prerendering a tree (i.e. with Offscreen) should not suspend the commit
phase, because the content is not yet visible. However, when revealing a
prerendered tree, we should suspend the commit phase if resources in the
prerendered tree haven't finished loading yet.

To do this properly, we need to visit all the visible nodes in the tree
that might possibly suspend. This includes nodes in the current tree,
because even though they were already "mounted", the resources might not
have loaded yet, because we didn't suspend when it was prerendered.

We will need to add this capability to the Offscreen component's
"manual" mode, too. Something like a `ready()` method that returns a
promise that resolves when the tree has fully loaded.

Also includes some fixes to #26450. See PR for details.
2023-03-26 23:48:37 -04:00
Sebastian Silbermann d12bdcda69
Fix Flow types of useEffectEvent (#26468)
## Summary

Just copied the types over from the internal types. Type error was
hidden by overly broad FlowFixMe. With `$FlowFixMe[not-a-function]` we
would've seen the actual issue:
```
Cannot return `dispatcher.useEffectEvent(...)` because  `T` [1] is incompatible with  undefined [2].Flow(incompatible-return)
```

## How did you test this change?

- [x] yarn flow dom-node
- [x] CI
2023-03-25 20:24:00 +01:00
Josh Story 73b6435ca4
[Float][Fiber] Implement waitForCommitToBeReady for stylesheet resources (#26450)
Before a commit is finished if any new stylesheet resources are going to
mount and we are capable of delaying the commit we will do the following

1. Wait for all preloads for newly created stylesheet resources to load
2. Once all preloads are finished we insert the stylesheet instances for
these resources and wait for them all to load
3. Once all stylesheets have loaded we complete the commit

In this PR I also removed the synchronous loadingstate tracking in the
fizz runtime. It was not necessary to support the implementation on not
used by the fizz runtime itself. It makes the inline script slightly
smaller

In this PR I also integrated ReactDOMFloatClient with
ReactDOMHostConfig. It leads to better code factoring, something I
already did on the server a while back. To make the diff a little easier
to follow i make these changes in a single commit so you can look at the
change after that commit if helpful

There is a 500ms timeout which will finish the commit even if all
suspended host instances have not finished loading yet

At the moment error and load events are treated the same and we're
really tracking whether the host instance is finished attempting to
load.
2023-03-24 19:17:38 -07:00
dan 175962c10c
Fix remaining CommonJS imports after Rollup upgrade (#26473)
Follow-up to https://github.com/facebook/react/pull/26442.

It looks like we missed a few cases where we default import a CommonJS
module, which leads to Rollup adding `.default` access, e.g.
`require('webpack/lib/Template').default` in the output.

To fix, add the remaining cases to the list of exceptions. Verified by
going through all `externals` in the bundle list, and manually checking
the webpack plugin.
2023-03-25 00:05:23 +00:00
Mengdi Chen 3fcf209ea4
React DevTools 4.27.3 -> 4.27.4 (#26470) 2023-03-24 15:45:26 -04:00
Mengdi Chen bde974ae40
[DevTools] missing file name in package.json (#26469)
resolves
https://github.com/facebook/react/pull/26337#issuecomment-1483004732
2023-03-24 14:45:27 -04:00
Mark Erikson 909c6dacfd
Update Rollup to 3.x (#26442)
<!--
  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

This PR:

- Updates Rollup from 2.x to latest 3.x, and updates associated plugins
- Updates deprecated / altered config settings in the Rollup plugin
pipeline
- Fixes some file extension and import issues related to use of ESM in
`react-dom-webpack-server`
- Removes a now-obsolete `strip-unused-imports` Rollup plugin
- <s>Fixes an _existing_ bug with the Rollup 2.x plugin pipeline on
`main` that was causing parts of `DOMProperty.js` to get left out of the
`react-dom-webpack-server` JS bundles, by adding a new plugin to tell
Rollup to treat that file as if it as side effects</s>

This PR should be functionally identical to the other existing "Rollup 3
upgrade" PR at #26078 . I'm filing this as a near-duplicate because I'm
ready to push this change through ASAP so that I can follow it up with a
PR that adds sourcemap support, that PR's artifact diffing seems like
it's possibly stuck and I want to compare the build results, and I've
got this set up against latest `main`.

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

This gets React's build setup updated to the latest Rollup version,
which is generally a good practice, but also ensures that any further
Rollup config tweaks can be done using the current Rollup docs as a
reference.

## 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.
-->

- Made builds from the latest `main`
- Updated Rollup package versions and cross-compared the changes I
needed to make locally to get successful builds vs #26078
- Diffed the output folders between `main` and this PR, and confirmed
that the bundle contents are identical (with the exception of version
strings and the `react-dom-webpack-server` bundle fix re-adding missing
`DOMProperty.js` content)
2023-03-24 18:08:41 +00:00
Rubén Norte 9c54b29b44
Remove ReactFabricPublicInstance and used definition from ReactNativePrivateInterface (#26437)
## Summary

Now that React Native owns the definition for public instances in Fabric
and ReactNativePrivateInterface provides the methods to create instances
and access private fields (see
https://github.com/facebook/react-native/pull/36570), we can remove the
definitions from React.

After this PR, React Native public instances will be opaque types for
React and it will only handle their creation but not their definition.
This will make RN similar to DOM in how public instances are handled.

This is a new version of #26418 which was closed without merging.

## How did you test this change?

* Existing tests.
* Manually synced the changes in this PR to React Native and tested it
end to end in Meta's infra.
2023-03-22 17:54:36 +00:00
Ricky f77099b6f1
Remove layout effect warning on the server (#26395)
## Overview

This PR unfortunately removes the warning emitted when using layout
effects on the server:

> useLayoutEffect does nothing on the server, because its effect cannot
be encoded into the server renderer's output format. This will lead to a
mismatch between the initial, non-hydrated UI and the intended UI. To
avoid this, useLayoutEffect should only be used in components that
render exclusively on the client. See
https://reactjs.org/link/uselayouteffect-ssr for common fixes.

## Why this warning exists
The new docs explain this really well. Adding a screenshot because as
part of this change, we'll be removing these docs.

<img width="1562" alt="Screenshot 2023-03-15 at 10 56 17 AM"
src="https://user-images.githubusercontent.com/2440089/225349148-f0e57c3f-95f5-4f2e-9178-d9b9b221c28d.png">

## Why are we changing it

In practice, users are not just ignoring this warning, but creating
hooks to bypass this warning by switching the useLayoutEffect hook on
the server instead of fixing it. This battle seems to be lost, so let's
remove the warning so at least users don't need to use the indirection
hook any more. In practice, if it's an issue, you should see the
problems like flashing the wrong content on first load in development.
2023-03-22 13:33:48 -04:00
Andrew Clark 51a7c45f87
Bugfix: SuspenseList incorrectly forces a fallback (#26453)
Fixes a bug in SuspenseList that @kassens found when deploying React to
Meta. In some scenarios, SuspenseList would force the fallback of a
deeply nested Suspense boundary into fallback mode, which should never
happen under any circumstances — SuspenseList should only affect the
nearest descendent Suspense boundaries, without going deeper.

The cause was that the internal ForceSuspenseFallback context flag was
not being properly reset when it reached the nearest Suspense boundary.
It should only be propagated shallowly.

We didn't discover this earlier because the scenario where it happens is
not that common. To trigger the bug, you need to insert a new Suspense
boundary into an already-mounted row of the list. But often when a new
Suspense boundary is rendered, it suspends and shows a fallback, anyway,
because its content hasn't loaded yet.

Another reason we didn't discover this earlier is because there was
another bug that was accidentally masking it, which was fixed by #25922.
When that fix landed, it revealed this bug.

The SuspenseList implementation is complicated but I'm not too concerned
with the current messiness. It's an experimental API, and we intend to
release it soon, but there are some known flaws and missing features
that we need to address first regardless. We'll likely end up rewriting
most of it.

Co-authored-by: Jan Kassens <jkassens@meta.com>
2023-03-22 13:33:02 -04:00
Sebastian Markbåge afb3d51dc6
Fix enableClientRenderFallbackOnTextMismatch flag (#26457)
With this flag off, we don't throw and therefore don't patch up the tree
when suppression is off.

Haven't tested.

---------

Co-authored-by: Rick Hanlon <rickhanlonii@fb.com>
2023-03-22 13:12:41 -04:00
Rubén Norte 8e17bfd144
Make InternalInstanceHandle type opaque in ReactNativeTypes (#26461)
## Summary

This type was defined as `mixed` to avoid bringing the whole definition
from React to React Native, but its definition is visible to RN. This
type should be opaque to RN, so this makes it explicit.

## How did you test this change?

Applied the same changes in the React Native repository and could use
the type without issues.
2023-03-22 15:39:52 +00:00
Mengdi Chen 8bdf162bcc
React DevTools 4.27.2 -> 4.27.3 (#26459)
bump version
2023-03-22 11:20:10 -04:00
Sebastian Markbåge b93b4f0745
Should not throw for children of iframe or object (#26458)
Still needs a regression test to test this for the future.
2023-03-22 13:56:20 +01:00
Leedom c0b34bc5fb
chore: update links of docs and api (#26455)
Update new links of docs and api  for react package.
> [Documentation](https://react.dev/)
> [API](https://react.dev/reference/react)
2023-03-22 12:56:18 +01:00
Leedom 56f7a90e68
chore: update new docs links for react-dom (#26456)
Update new documentation links in react-dom's readme.
> [react-dom](https://react.dev/reference/react-dom)
> [react-dom/client](https://react.dev/reference/react-dom/client)
> [react-dom/server](https://react.dev/reference/react-dom/server)
2023-03-22 12:55:06 +01:00
Jan Kassens bd5e32309d
Small Flow upgrade to 0.202.0 (#26435)
Easy upgrade.

`exact_by_default=true` is now the default, so we can remove it.
2023-03-22 12:52:13 +01:00
Valor(华洛) ffb6733eef
fix docs link for useSyncExternalStore (#26452)
## Summary

Update readme to new documentation links to
[`React.useSyncExternalStore`](https://react.dev/reference/react/useSyncExternalStore

## How did you test this change?

This is just a documentation change, so we don't need to test it

Co-authored-by: 田源 <tianyuan@eol.cn>
2023-03-22 01:39:05 +00:00
Samuel Susla 0018cf2246
Add REVISION file to react-fbsource-import (#26448)
For DiffTrain to fbsource, we need REVISION file in compiled-rn folder
2023-03-21 16:18:20 +00:00
Andrew Clark 12a1d140e3
Don't prerender siblings of suspended component (#26380)
Today if something suspends, React will continue rendering the siblings
of that component.

Our original rationale for prerendering the siblings of a suspended
component was to initiate any lazy fetches that they might contain. This
was when we were more bullish about lazy fetching being a good idea some
of the time (when combined with prefetching), as opposed to our latest
thinking, which is that it's almost always a bad idea.

Another rationale for the original behavior was that the render was I/O
bound, anyway, so we might as do some extra work in the meantime. But
this was before we had the concept of instant loading states: when
navigating to a new screen, it's better to show a loading state as soon
as you can (often a skeleton UI), rather than delay the transition.
(There are still cases where we block the render, when a suitable
loading state is not available; it's just not _all_ cases where
something suspends.) So the biggest issue with our existing
implementation is that the prerendering of the siblings happens within
the same render pass as the one that suspended — _before_ the loading
state appears.

What we should do instead is immediately unwind the stack as soon as
something suspends, to unblock the loading state.

If we want to preserve the ability to prerender the siblings, what we
could do is schedule special render pass immediately after the fallback
is displayed. This is likely what we'll do in the future. However, in
the new implementation of `use`, there's another reason we don't
prerender siblings: so we can preserve the state of the stack when
something suspends, and resume where we left of when the promise
resolves without replaying the parents. The only way to do this
currently is to suspend the entire work loop. Fiber does not currently
support rendering multiple siblings in "parallel". Once you move onto
the next sibling, the stack of the previous sibling is discarded and
cannot be restored. We do plan to implement this feature, but it will
require a not-insignificant refactor.

Given that lazy data fetching is already bad for performance, the best
trade off for now seems to be to disable prerendering of siblings. This
gives us the best performance characteristics when you're following best
practices (i.e. hoist data fetches to Server Components or route
loaders), at the expense of making an already bad pattern a bit worse.

Later, when we implement resumable context stacks, we can reenable
sibling prerendering. Though even then the use case will mostly be to
prerender the CPU-bound work, not lazy fetches.
2023-03-21 10:24:56 -04:00
Andrew Clark 77ba1618a5
Bugfix: Remove extra render pass when reverting to client render (#26445)
(This was reviewed and approved as part of #26380; I'm extracting it
into its own PR so that it can bisected later if it causes an issue.)

I noticed while working on a PR that when an error happens during
hydration, and we revert to client rendering, React actually does _two_
additional render passes instead of just one. We didn't notice it
earlier because none of our tests happened to assert on how many renders
it took to recover, only on the final output.

It's possible this extra render pass had other consequences that I'm not
aware of, like messing with some assumption in the recoverable errors
logic.

This adds a test to demonstrate the issue. (One problem is that we don't
have much test coverage of this scenario in the first place, which
likely would have caught this earlier.)
2023-03-20 22:07:53 -04:00
Sebastian Markbåge 520f7f3ed4
Refactor ReactDOMComponent to use flatter property operations (#26433)
This is in line with the refactor I already did on Fizz earlier and
brings Fiber up to a similar structure.

We end up with a lot of extra checks due the extra abstractions we use
to check the various properties. This uses a flatter and more inline
model which makes it easier to see what each property does. The tradeoff
is that a change might need changes in more places.

The general structure is that there's a switch for tag first, then a
switch for each attribute special case, then a switch for the value. So
it's easy to follow where each scenario will end up and there shouldn't
be any unnecessary code executed along the way.

My goal is to eventually get rid of the meta-programming in DOMProperty
and CSSProperty but I'm leaving that in for now - in line with Fizz.

My next step is moving around things a bit in the diff/commit phases.
This is the first step to more refactors for perf and size, but also
because I'm adding more special cases so I need to have a flatter
structure that I can reason about for those special cases.
2023-03-20 20:56:14 -04:00
Andrew Clark 0131d0cff4
Check if suspensey instance resolves in immediate task (#26427)
When rendering a suspensey resource that we haven't seen before, it may
have loaded in the background while we were rendering. We should yield
to the main thread to see if the load event fires in an immediate task.

For example, if the resource for a link element has already loaded, its
load event will fire in a task right after React yields to the main
thread. Because the continuation task is not scheduled until right
before React yields, the load event will ping React before it resumes.

If this happens, we can resume rendering without showing a fallback.

I don't think this matters much for images, because the `completed`
property tells us whether the image has loaded, and during a non-urgent
render, we never block the main thread for more than 5ms at a time (for
now — we might increase this in the future). It matters more for
stylesheets because the only way to check if it has loaded is by
listening for the load event.

This is essentially the same trick that `use` does for userspace
promises, but a bit simpler because we don't need to replay the host
component's begin phase; the work-in-progress fiber already completed,
so we can just continue onto the next sibling without any additional
work.

As part of this change, I split the `shouldSuspendCommit` host config
method into separate `maySuspendCommit` and `preloadInstance` methods.
Previously `shouldSuspendCommit` was used for both.

This raised a question of whether we should preload resources during a
synchronous render. My initial instinct was that we shouldn't, because
we're going to synchronously block the main thread until the resource is
inserted into the DOM, anyway. But I wonder if the browser is able to
initiate the preload even while the main thread is blocked. It's
probably a micro-optimization either way because most resources will be
loaded during transitions, not urgent renders.
2023-03-20 12:35:10 -04:00
Rubén Norte 3554c8852f
Clean interface for public instances between React and React Native (#26416)
## Summary

We are going to move the definition of public instances from React to
React Native to have them together with the native methods in Fabric
that they invoke. This will allow us to have a better type safety
between them and iterate faster on the implementation of this proposal:
https://github.com/react-native-community/discussions-and-proposals/pull/607

The interface between React and React Native would look like this after
this change and a following PR (#26418):

React → React Native:
```javascript
ReactNativePrivateInterface.createPublicInstance // to provide via refs
ReactNativePrivateInterface.getNodeFromPublicInstance // for DevTools, commands, etc.
ReactNativePrivateInterface.getNativeTagFromPublicInstance // to implement `findNodeHandle`
```

React Native → React (ReactFabric):
```javascript
ReactFabric.getNodeFromInternalInstanceHandle // to get most recent node to call into native
ReactFabric.getPublicInstanceFromInternalInstanceHandle // to get public instances from results from native
```

## How did you test this change?

Flow
Existing unit tests
2023-03-20 13:35:18 +00:00
Samuel Susla c57b90f50d
[DiffTrain] Add artifacts for React Native to compiled (#26204) 2023-03-20 11:23:55 +00:00
Andrew Clark 842bd787a5
Fix sizebot not working due to missing auth token (#26423)
Sizebot works by fetching the base artifacts from CI. CircleCI recently
updated this endpoint to require an auth token. This is a problem for PR
branches, where sizebot runs, because we don't want to leak the token to
arbitrary code written by an outside contributor.

This only affects PR branches. CI workflows that run on the main branch
are allowed to access environment variables, because only those with
push access can land code in main.

As a temporary workaround, we'll fetch the assets from a mirror,
react-builds.vercel.app. This is the same app that hosts the sizebot
diff previews.

Need to figure out a longer term solution. Perhaps by converting sizebot
into a proper GitHub app.
2023-03-18 16:22:20 -04:00
Andrew Clark db281b3d9c
Feature: Suspend commit without blocking render (#26398)
This adds a new capability for renderers (React DOM, React Native):
prevent a tree from being displayed until it is ready, showing a
fallback if necessary, but without blocking the React components from
being evaluated in the meantime.

A concrete example is CSS loading: React DOM can block a commit from
being applied until the stylesheet has loaded. This allows us to load
the CSS asynchronously, while also preventing a flash of unstyled
content. Images and fonts are some of the other use cases.

You can think of this as "Suspense for the commit phase". Traditional
Suspense, i.e. with `use`, blocking during the render phase: React
cannot proceed with rendering until the data is available. But in the
case of things like stylesheets, you don't need the CSS in order to
evaluate the component. It just needs to be loaded before the tree is
committed. Because React buffers its side effects and mutations, it can
do work in parallel while the stylesheets load in the background.

Like regular Suspense, a "suspensey" stylesheet or image will trigger
the nearest Suspense fallback if it hasn't loaded yet. For now, though,
we only do this for non-urgent updates, like with startTransition. If
you render a suspensey resource during an urgent update, it will revert
to today's behavior. (We may or may not add a way to suspend the commit
during an urgent update in the future.)

In this PR, I have implemented this capability in the reconciler via new
methods added to the host config. I've used our internal React "no-op"
renderer to write tests that demonstrate the feature. I have not yet
implemented Suspensey CSS, images, etc in React DOM. @gnoff and I will
work on that in subsequent PRs.
2023-03-17 18:05:11 -04:00
lauren 6310087f09
[ci] Fix download_base_build_for_sizebot (#26422)
CircleCI now enforces passing a token when fetching artifacts. I'm also
deleting the old request-promise-json dependency because AFAIK we were
only using it to fetch json from circleci about the list of available
artifacts – which we can just do using node-fetch. Plus, the underlying
request package it uses has been deprecated since 2019.
2023-03-17 13:04:20 -07:00
lauren 6854a3cf6d
[difftrain] Fix broken workflow (#26421)
Seems like CircleCI now enforces passing a token when fetching
artifacts. I provisioned a new read-only CircleCI token just for
difftrain.

test plan: see https://github.com/facebook/react/actions/runs/4450679268
2023-03-17 12:16:55 -07:00
Jan Kassens 55308554ed
[www] enable enableFilterEmptyStringAttributesDOM flag (#26410) 2023-03-17 12:09:36 -04:00
Ibrahim Amin 163d86e195
Updated comment message (#26158)
a simple grammar fix.
2023-03-17 14:48:44 +00:00
Rubén Norte 108aed083e
Fix use of stale props in Fabric events (#26408)
## Summary

We had to revert the last React sync to React Native because we saw
issues with Responder events using stale event handlers instead of
recent versions.

I reviewed the merged PRs and realized the problem was in the refactor I
did in #26321. In that PR, we moved `currentProps` from `canonical`,
which is a singleton referenced by all versions of the same fiber, to
the fiber itself. This is causing the staleness we observed in events.

This PR does a partial revert of the refactor in #26321, bringing back
the `canonical` object but moving `publicInstance` to one of its fields,
instead of being the `canonical` object itself.

## How did you test this change?

Existing unit tests continue working (I didn't manage to get a repro
using the test renderer).
I manually tested this change in Meta infra and saw the problem was
fixed.
2023-03-17 11:27:49 +00:00
Sebastian Markbåge 8fa41ffa27
Don't "fix up" mismatched text content with suppressedHydrationWarning (#26391)
In concurrent mode we error if child nodes mismatches which triggers a
recreation of the whole hydration boundary. This ensures that we don't
replay the wrong thing, transform state or other security issues.

For text content, we respect `suppressedHydrationWarning` to allow for
things like `<div suppressedHydrationWarning>{timestamp}</div>` to
ignore the timestamp. This mode actually still patches up the text
content to be the client rendered content.

In principle we shouldn't have to do that because either value should be
ok, and arguably it's better not to trigger layout thrash after the
fact.

We do have a lot of code still to deal with patching up the tree because
that's what legacy mode does which is still in the code base. When we
delete legacy mode we would still be stuck with a lot of it just to deal
with this case.

Therefore I propose that we change the semantics to not patch up
hydration errors for text nodes. We already don't for attributes.
2023-03-16 22:39:17 -04:00
Tianyu Yao 87c803d1da
Fix a test case in ReactUpdates-test (#26399)
Just noticed the test isn't testing what it is meant to test properly.
The error `Warning: ReactDOM.render is no longer supported in React 18.
Use createRoot instead. Until you switch to the new API, your app will
behave as if it's running React 17. Learn more:
https://reactjs.org/link/switch-to-createroot` is thrown, the inner
`expect(error).toContain('Warning: Maximum update depth exceeded.');`
failed and threw jest error, and the outer `.toThrow('Maximum update
depth exceeded.')` happens to catch it and makes the test pass.
2023-03-16 12:27:15 -07:00
Jan Kassens eaccf27c2e
Revert "Remove hydrate entry point from www builds" (#26413)
Reverts facebook/react#26400.

Will take a look at the test failures before re-merging.
2023-03-16 14:01:20 -04:00
Sebastian Markbåge 480aa7785f
Remove hydrate entry point from www builds (#26400)
As I understand it this isn't used at Meta and it would let us get rid
of at least legacy mode hydration code when we remove legacy mode from
OSS builds.
2023-03-16 11:39:34 -04:00
Ricky 9941cbacac
Fix devtools tests after internal test changes (#26405) 2023-03-16 08:14:23 -04:00
Jarred Sumner e4606c1e0e
Add missing `"react-dom/server.bun"` entry in package.json `"exports"` (#26402)
<!--
  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?
-->

`react-dom/server` in Bun (correctly) chooses `react-dom/server.bun`,
but `react-dom/server.bun` currently can't be imported because it is not
included in package.json `"exports"` (`react-dom/server` works,
`react-dom/server.bun` doesn't). Previously, I didn't think it was
necessary to do that, but it is too easy to accidentally run the browser
build in unit tests when importing `react-dom/server`

This also aligns behavior of package.json `"exports"` of
`react-dom/server.bun` with `react-dom/server.browser`,
`react-dom/server.node`, and the rest.

## How did you test this change?

Manually edited package.json in node_modules in a separate folder and
ran tests in Bun with `react-dom/server.bun` as the import specifier

<!--
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.
-->
2023-03-15 22:09:49 -04:00
Sophie Alpert 05777ffb01
Setting transition pending flag shouldn't be part of a surrounding transition (#26243)
Fixes #26226. (Is this the right fix?)
2023-03-15 18:10:53 -07:00
Ricky 21f6dba6a7
Sync from oss-experimental, not oss-stable (#26401)
## Overview

To test useEffectEvent, we need the experimental build of the lint
plugin.
2023-03-15 21:01:07 -04:00
Jan Kassens 99aa082be0
Remove unstable_flushControlled (#26397)
This API has been fully replaced by `flushSync`.
2023-03-15 16:13:54 -04:00
Rubén Norte 47cf4e578c
Restore some guards in ReactFabricGlobalResponderHandler after refactor (#26394)
## Summary

I refactored this code in #26290 but forgot to add guards when the fiber
or the state node where null, and this is typed as `any` so Flow didn't
catch it.

This restores the same logic to guard against null.

## How did you test this change?

Existing tests.
2023-03-15 10:30:40 +00:00
Sebastian Markbåge cfc1274e3b
Disable IE innerHTML workaround behind a flag (#26390)
We don't need this workaround for SVG anymore and we don't need to
workaround MSApp's security model since Windows 10.
2023-03-14 23:27:04 -04:00
Sebastian Markbåge a57f40d839
Undo dependency injection of batching (#26389)
There's currently a giant cycle between the event system, through
react-dom-bindings, reconciler and then react-dom. We resolve this cycle
using dependency injection. However, this all ends up in the same
bundle. It can be reordered to resolve the cycles. If we avoid
side-effects and avoid reading from module exports during
initialization, this should be resolvable in a more optimal way by the
compiler.
2023-03-14 21:40:43 -04:00
Sebastian Markbåge d310d654a7
Avoid meta programming to initialize functions in module scope (#26388)
I'm trying to get rid of all meta programming in the module scope so
that closure can do a better job figuring out cyclic dependencies and
ability to reorder.

This is converting a lot of the patterns that assign functions
conditionally to using function declarations instead.

```
let fn;
if (__DEV__) {
  fn = function() {
    ...
  };
}
```
->
```
function fn() {
  if (__DEV__) {
    ...
  }
}
```
2023-03-14 21:00:22 -04:00
Sebastian Markbåge 21aee59e45
Delete unused DOM files (#26387)
These used to be used by partial render.

ReactDOMDispatcher ended up not being used in this way.

Move shared DOM files to client. These are only used by client
abstractions now. They're inlined in the Fizz code so they're no longer
shared.
2023-03-14 19:52:57 -04:00
Andrew Clark 56a3c18e56
[Flight fixture] Remove redundant `use` (#26373)
Now that promises are renderable nodes, we can remove the `use` call
from the root of the Flight fixture.

Uncached promises will likely be accompanied by a warning when they are
rendered outside a transition. But this promise is the result of a
Flight response, so it's cached. And it's also a rendered as part of a
transition. So it's fine. Indeed, this is the canonical way to use this
feature.
2023-03-14 11:14:53 -04:00
Sebastian Markbåge 6bd53a5bdf
Remove FeatureFlags fork for `react-dom/unstable_testing` (#26383)
This doesn't need its own set of flags. We use things like `__PROFILE__`
in the regular feature flags file to fork for the `react-dom/profiling`
build so we can do the same here if needed but I don't think we actually
need to fork this anywhere as far as I can tell.
2023-03-13 18:43:37 -04:00
Sebastian Markbåge 2788d0d8dd
Allow empty string to be passed to formAction (#26379)
We disallow empty strings for `href` and `src` since they're common
mistakes that end up loading the current page as a preload, image or
link. We also disallow it for `action`. You have to pass `null` which is
the same.

However, for `formAction` passing `null` is not the same as passing
empty string. Passing empty string overrides the form's action to be the
current page even if the form's action was set to something else.
There's no easy way to express the same thing `#` show up in the user
visible URLs and `?` clears the search params.

Since this is also not a common mistake, we can just allow this.
2023-03-13 14:28:17 -04:00
Rubén Norte f828bad387
Extracted definition and access to public instances to a separate module in Fabric (#26321)
## Summary

The current definition of `Instance` in Fabric has 2 fields:
- `node`: reference to the native node in the shadow tree.
- `canonical`: public instance provided to users via refs + some
internal fields needed by Fabric.

We're currently using `canonical` not only as the public instance, but
also to store internal properties that Fabric needs to access in
different parts of the codebase. Those properties are, in fact,
available through refs as well, which breaks encapsulation.

This PR splits that into 2 separate fields, leaving the definition of
instance as:
- `node`: reference to the native node in the shadow tree.
- `publicInstance`: public instance provided to users via refs.
- Rest of internal fields needed by Fabric at the instance level.

This also migrates all the current usages of `canonical` to use the
right property depending on the use case.

To improve encapsulation (and in preparation for the implementation of
this [proposal to bring some DOM APIs to public instances in React
Native](https://github.com/react-native-community/discussions-and-proposals/pull/607)),
this also **moves the creation of and the access to the public instance
to separate modules** (`ReactFabricPublicInstance` and
`ReactFabricPublicInstanceUtils`). In a following diff, that module will
be moved into the `react-native` repository and we'll access it through
`ReactNativePrivateInterface`.

## How did you test this change?

Existing unit tests.
Manually synced the PR in Meta infra and tested in Catalyst + the
integration with DevTools. Everything is working normally.
2023-03-13 13:25:42 +00:00
Andrew Clark cd20376f03
Remove internal `act` from DevTools e2e test (#26376)
For various reasons some of the DevTools e2e tests uses our repo's
private internal version of `act`. It should really just be using the
public one.

This converts one of the usages, because it was causing CI to fail.
2023-03-12 12:58:58 -04:00
Andrew Clark 131768166b
Support Context as renderable node (#25641)
## Based on #25634

Like promises, this adds support for Context as a React node.

In this initial implementation, the context dependency is added to the
parent of child node. This allows the parent to re-reconcile its
children when the context updates, so that it can delete the old node if
the identity of the child has changed (i.e. if the key or type of an
element has changed). But it also means that the parent will replay its
entire begin phase. Ideally React would delete the old node and mount
the new node without reconciling all the children. I'll leave this for a
future optimization.
2023-03-11 17:34:31 -05:00
Andrew Clark d4f58c3b81
Support Promise as a renderable node (#25634)
Implements Promise as a valid React node types. The idea is that any
type that can be unwrapped with `use` should also be renderable.

When the reconciler encounters a Usable in a child position, it will
transparently unwrap the value before reconciling it. The value of the
inner value will determine the identity of the child during
reconciliation, not the Usable object that wraps around it.

Unlike `use`, the reconciler will recursively unwrap the value until it
reaches a non-Usable type, e.g. `Usable<Usable<Usable<T>>>` will resolve
to T.

In this initial commit, I've added support for Promises. I will do
Context in the [next
step](https://github.com/facebook/react/pull/25641).

Being able to render a promise as a child has several interesting
implications. The Server Components response format can use this feature
in its implementation — instead of wrapping references to client
components in `React.lazy`, it can just use a promise.

This also fulfills one of the requirements for async components on the
client, because an async component always returns a promise for a React
node. However, we will likely warn and/or lint against this for the time
being because there are major caveats if you re-render an async
component in response to user input. (Note: async components already
work in a Server Components environment — the caveats only apply to
running them in the browser.)

To suspend, React uses the same algorithm as `use`: by throwing an
exception to unwind the stack, then replaying the begin phase once the
promise resolves. It's a little weird to suspend during reconciliation,
however, `lazy` already does this so if there were any obvious bugs
related to that we likely would have already found them.

Still, the structure is a bit unfortunate. Ideally, we shouldn't need to
replay the entire begin phase of the parent fiber in order to reconcile
the children again. This would require a somewhat significant refactor,
because reconciliation happens deep within the begin phase, and
depending on the type of work, not always at the end. We should consider
as a future improvement.
2023-03-11 17:11:27 -05:00
Andrew Clark f411e8990f
Remote `.internal` override from untrusted URL tests (#26372)
Adding `.internal` to a test file prevents it from being tested in build
mode. The best practice is to instead gate the test based on whether the
feature is enabled.

Ideally we'd use the `@gate` pragma in these tests, but the `itRenders`
test helpers don't support that.
2023-03-11 15:46:16 -05:00
Andrew Clark 6334614860
Add disableLegacyContext test gates where needed (#26371)
The www builds include disableLegacyContext as a dynamic flag, so we
should be running the tests in that mode, too. Previously we were
overriding the flag during the test run. This strategy usually doesn't
work because the flags get compiled out in the final build, but we
happen to not test www in build mode, only source.

To get of this hacky override, I added a test gate to every test that
uses legacy context. When we eventually remove legacy context from the
codebase, this should make it slightly easier to find which tests are
affected. And removes one more hack from our hack-ridden test config.

Given that sometimes www has features enabled that aren't on in other
builds, we might want to consider testing its build artifacts in CI,
rather than just source. That would have forced this cleanup to happen
sooner. Currently we only test the public builds in CI.
2023-03-11 15:32:02 -05:00
Tianyu Yao 432ffc9d0f
Convert more Scheduler.unstable_flushAll in tests to new test utils (#26369)
`Scheduler.unstable_flushAll` in existing tests doesn't work with
microtask. This PR converts most of the remaining
`Scheduler.unstable_flushAll()` calls to using internal test utilities
to unblock refactoring `ensureRootIsScheduled` with scheduling a
microtask.
2023-03-10 20:56:13 -05:00
Sebastian Markbåge 774111855d
[Flight Fixture] Fix proxying with compression (#26368)
We're decompressing and then writing and recompressing in the proxy.
This causes it to stall if buffered because `.pipe()` doesn't force
flush automatically.
2023-03-10 19:48:46 -05:00
Andrew Clark 69fd78fe37
Update Float tests to check for specific errors (#26367)
I updated some of the Float tests that intentionally trigger an error to
assert on the specific error message, rather than swallow any errors
that may or may not happen.
2023-03-10 18:37:32 -05:00
Andrew Clark 93c10dfa6b
flushSync: Exhaust queue even if something throws (#26366)
If something throws as a result of `flushSync`, and there's remaining
work left in the queue, React should keep working until all the work is
complete.

If multiple errors are thrown, React will combine them into an
AggregateError object and throw that. In environments where
AggregateError is not available, React will rethrow in an async task.
(All the evergreen runtimes support AggregateError.)

The scenario where this happens is relatively rare, because `flushSync`
will only throw if there's no error boundary to capture the error.
2023-03-10 17:21:34 -05:00
Mengdi Chen a22bd995c5
[DevTools] prevent StyleX plugin from throwing when inspecting CSS (#26364)
## Summary

An error might happen when we try to read the CSS rules, but the
stylesheet does not allow so (often happens on production).

Before:
<img width="713" alt="image"
src="https://user-images.githubusercontent.com/1001890/224376546-024f7a32-d314-4dd1-9333-7e47d96a2b7c.png">

After:

<img width="504" alt="image"
src="https://user-images.githubusercontent.com/1001890/224376426-964a33c4-0677-4a51-91c2-74074e4dde63.png">


## How did you test this change?

Built a fb version and tested locally (see above screenshot)

---------

Co-authored-by: Hendrik Liebau <mail@hendrik-liebau.de>
2023-03-10 15:43:05 -05:00
Sebastian Markbåge be353d2515
[Flight Reply] Add undefined and Iterable Support (#26365)
These were recently added to ReactClientValue and so needs to be
reflected in ReactServerValue too.
2023-03-10 12:47:43 -05:00
Sebastian Markbåge ef8bdbecb6
[Flight Reply] Add Reply Encoding (#26360)
This adds `encodeReply` to the Flight Client and `decodeReply` to the
Flight Server.

Basically, it's a reverse Flight. It serializes values passed from the
client to the server. I call this a "Reply". The tradeoffs and
implementation details are a bit different so it requires its own
implementation but is basically a clone of the Flight Server/Client but
in reverse. Either through callServer or ServerContext.

The goal of this project is to provide the equivalent serialization as
passing props through RSC to client. Except React Elements and
Components and such. So that you can pass a value to the client and back
and it should have the same serialization constraints so when we add
features in one direction we should mostly add it in the other.

Browser support for streaming request bodies are currently very limited
in that only Chrome supports it. So this doesn't produce a
ReadableStream. Instead `encodeReply` produces either a JSON string or
FormData. It uses a JSON string if it's a simple enough payload. For
advanced features it uses FormData. This will also let the browser
stream things like File objects (even though they're not yet supported
since it follows the same rules as the other Flight).

On the server side, you can either consume this by blocking on
generating a FormData object or you can stream in the
`multipart/form-data`. Even if the client isn't streaming data, the
network does. On Node.js busboy seems to be the canonical library for
this, so I exposed a `decodeReplyFromBusboy` in the Node build. However,
if there's ever a web-standard way to stream form data, or if a library
wins in that space we can support it. We can also just build a multipart
parser that takes a ReadableStream built-in.

On the server, server references passed as arguments are loaded from
Node or Webpack just like the client or SSR does. This means that you
can create higher order functions on the client or server. This can be
tokenized when done from a server components but this is a security
implication as it might be tempting to think that these are not fungible
but you can swap one function for another on the client. So you have to
basically treat an incoming argument as insecure, even if it's a
function.

I'm not too happy with the naming parity:

Encode `server.renderToReadableStream` Decode: `client.createFromFetch`

Decode `client.encodeReply` Decode: `server.decodeReply`

This is mainly an implementation details of frameworks but it's annoying
nonetheless. This comes from that `renderToReadableStream` does do some
"rendering" by unwrapping server components etc. The `create` part comes
from the parity with Fizz/Fiber where you `render` on the server and
`create` a root on the client.

Open to bike-shedding this some more.

---------

Co-authored-by: Josh Story <josh.c.story@gmail.com>
2023-03-10 11:36:15 -05:00
Andrew Clark a8875eab7f
Update more tests to not rely on sync queuing (#26358)
This fixes a handful of tests that were accidentally relying on React
synchronously queuing work in the Scheduler after a setState.

Usually this is because they use a lower level SchedulerMock method
instead of either `act` or one of the `waitFor` helpers. In some cases,
the solution is to switch to those APIs. In other cases, if we're
intentionally testing some lower level behavior, we might have to be a
bit more clever.

Co-authored-by: Tianyu Yao <skyyao@fb.com>
2023-03-10 11:06:28 -05:00
Sebastian Silbermann d1ad984db1
[Flight] Add support for returning `undefined` from render (#26349)
## Summary

Adds support for returning `undefined` from Server Components.
Also fixes a bug where rendering an empty fragment would throw the same
error as returning undefined.

## How did you test this change?

- [x] test failed with same error message I got when returning undefined
from Server Components in a Next.js app
- [x] test passes after adding encoding for `undefined`
2023-03-09 22:18:52 +01:00
Andrew Clark 39d4b93657
[Internal tests] Close MessageChannel port to prevent leak (#26357)
Node's MessageChannel implementation will leak if you don't explicitly
close the port. This updates the enqueueTask function we use in our
internal testing helpers to close the port once it's no longer needed.
2023-03-09 11:20:07 -05:00
Josh Story 3706edb81c
[Float][Fizz]: Don't preload nomodule scripts (#26353)
We attempt to preload scripts that we detect during Fizz rendering
however when `noModule={true}` we should not because it will force
modern browser to fetch scripts they will never execute

Hoisted script resources already don't preload because we just emit the
resource immediately. This change currently on affects the preloads for
scripts that aren't hoistable
2023-03-08 21:59:43 -08:00
Sebastian Markbåge 2b003a5cc6
Split out ServerReferenceMetadata into Id and Bound Arguments (#26351)
This is just moving some stuff around and renaming things.

This tuple is opaque to the Flight implementation and we should probably
encode it separately as a single string instead of a model object.

The term "Metadata" isn't the same as when used for ClientReferences so
it's not really the right term anyway.

I also made it optional since a bound function with no arguments bound
is technically different than a raw instance of that function (it's a
clone).

I also renamed the type ReactModel to ReactClientValue. This is the
generic serializable type for something that can pass through the
serializable boundary from server to client. There will be another one
for client to server.

I also filled in missing classes and ensure the serializable sub-types
are explicit. E.g. Array and Thenable.
2023-03-08 23:45:55 -05:00
Andrew Clark 62cd5af08e
Codemod redundant async act scopes (#26350)
Prior to #26347, our internal `act` API (not the public API) behaved
differently depending on whether the scope function returned a promise
(i.e. was an async function), for historical reasons that no longer
apply. Now that this is fixed, I've codemodded all async act scopes that
don't contain an await to be sync.

No pressing motivation other than it looks nicer and the codemod was
easy. Might help avoid confusion for new contributors who see async act
scopes with nothing async inside and infer it must be like that for a
reason.
2023-03-08 16:40:23 -05:00
Andrew Clark 037378202f
Internal `act`: Call scope function after an async gap (#26347)
This adds an async gap to our internal implementation of `act` (the one
used by our repo, not the public API). Rather than call the provided
scope function synchronously when `act` is called, we call it in a
separate async task. This is an extra precaution to ensure that our
tests do not accidentally rely on work being queued synchronously,
because that is an implementation detail that we should be allowed to
change. We don't do this in the public version of `act`, though we maybe
should in the future, for the same rationale. That might be tricky,
though, because it could break existing tests.

This also fixes the issue where our internal `act` requires an async
function. You can pass it a regular function, too.
2023-03-08 16:25:12 -05:00
Sebastian Markbåge d8e49f2af8
Use setTimeout to schedule work on the server in Edge environments (#26348)
We rely heavily on being able to batch rendering after multiple fetches
etc. have completed on the server. However, we only do this in the
Node.js build. Node.js `setImmediate` has the exact semantics we need.
To be after the current cycle of I/O so that we can collect after all
those I/O events already in the queue has been processed.

This doesn't exist in standard browsers, so we ended up not using it
there. We could've used `setTimeout` but that risks being throttled
which would severely negatively affect the performance so we just did it
synchronously there. We probably could just use the `scheduler` there.

Now we have a separate build for Edge where `setTimeout(..., 0)`
actually behaves like `setImmediate` which is what we want. So we can
just use that in that build.

@Jarred-Sumner not sure what you want for Bun.
2023-03-08 15:34:29 -05:00
Andrew Clark 83643778bd
Internal test helpers: Use Node's MessageChannel to queue task (#26345)
To wait for the microtask queue to empty, our internal test helpers
schedule an arbitrary task using `setImmediate`. It doesn't matter what
kind of task it is, only that it's a separate task from the current one,
because by the time it fires, the microtasks for the current event will
have already been processed.

The issue with `setImmediate` is that Jest mocks it. Which can lead to
weird behavior.

I've changed it to instead use a message event, via the MessageChannel
implementation exposed by the `node:worker_threads` module.

We should consider doing this in the public implementation of `act`,
too.
2023-03-08 15:04:38 -05:00
Andrew Clark f36ab0e375
Remove timers from ReactDOMSuspensePlaceholder tests (#26346)
Our internal `act` implementation flushes Jest's fake timer queue as a
way to force Suspense fallbacks to appear. So we should avoid using
timers in our internal tests.
2023-03-08 14:45:35 -05:00
Andrew Clark 44d3807945
Move internalAct to internal-test-utils package (#26344)
This is not a public API. We only use it for our internal tests, the
ones in this repo. Let's move it to this private package. Practically
speaking this will also let us use async/await in the implementation.
2023-03-08 12:58:31 -05:00
Jan Kassens 8c100620ca
Build: specify Node.js 16 as minimum for dev (#26343)
- Specifies Node 16 as the minimum supported version.
- Remove no longer supported 17.x version (per
https://nodejs.dev/en/about/releases/)
- Add 19.x

Test Plan:
(using node 19) as that's what I'm adding)
- yarn build
- yarn test
2023-03-08 12:14:36 -05:00
Andrew Clark d814473047
[Internal API only] Delete non-awaited form of act (#26339)
**This commit only affects the internal version of `act` that we use in
this repo. The public `act` API is unaffected, for now.**

We should always await the result of an `act` call so that any work
queued in a microtask has a chance to flush. Neglecting to do this can
cause us to miss bugs when testing React behavior.

I codemodded all the existing `act` callers in previous PRs.
2023-03-08 11:46:10 -05:00
Andrew Clark 702fc984e6
Codemod act -> await act (4/?) (#26338)
Similar to the rationale for `waitFor` (see #26285), we should always
await the result of an `act` call so that microtasks have a chance to
fire.

This only affects the internal `act` that we use in our repo, for now.
In the public `act` API, we don't yet require this; however, we
effectively will for any update that triggers suspense once `use` lands.
So we likely will start warning in an upcoming minor.
2023-03-08 11:36:05 -05:00
Rubén Norte 9fb2469a63
Restore definition of NativeMethods as an object for React Native (#26341)
## Summary

In #26283, I changed definition of `NativeMethods` from an object to an
interface. This is correct but introduces a lot of errors in React
Native, so this restores the original definition and exports the fixed
type as a separate type so we can gradually migrate in React Native.

## How did you test this change?

Manually applied this change in React Native and validated the errors
are gone.
2023-03-08 14:37:37 +00:00
Mengdi Chen aef930314f
[DevTools] upgrade electron to latest version & security improvements (#26337)
## Summary

resolves #25667
This PR also resolves several security issues in the standalone app

## How did you test this change?

Tested locally `yarn start` in react-devtools package. Everything works
normal

---
- To see the specific tasks where the Asana app for GitHub is being
used, see below:
  - https://app.asana.com/0/0/1204123419819195
2023-03-07 22:31:54 -05:00
Andrew Clark 161f6ae42c
Codemod act -> await act (3/?) (#26336)
Similar to the rationale for `waitFor` (see #26285), we should always
await the result of an `act` call so that microtasks have a chance to
fire.

This only affects the internal `act` that we use in our repo, for now.
In the public `act` API, we don't yet require this; however, we
effectively will for any update that triggers suspense once `use` lands.
So we likely will start warning in an upcoming minor.
2023-03-07 14:39:30 -05:00
Andrew Clark 58605f7988
Codemod act -> await act (2/?) (#26335)
Similar to the rationale for `waitFor` (see #26285), we should always
await the result of an `act` call so that microtasks have a chance to
fire.

This only affects the internal `act` that we use in our repo, for now.
In the public `act` API, we don't yet require this; however, we
effectively will for any update that triggers suspense once `use` lands.
So we likely will start warning in an upcoming minor.
2023-03-07 12:07:30 -05:00
Andrew Clark 703c67560d
Codemod act -> await act (1/?) (#26334)
Similar to the rationale for `waitFor` (see
https://github.com/facebook/react/pull/26285), we should always await
the result of an `act` call so that microtasks have a chance to fire.

This only affects the internal `act` that we use in our repo, for now.
In the public `act` API, we don't yet require this; however, we
effectively will for any update that triggers suspense once `use` lands.
So we likely will start warning in an upcoming minor.
2023-03-07 10:15:34 -05:00
Andrew Clark b380c24852
Convert class equivlance tests to flushSync (#26333)
There's an old collection of test suites that test class component
behavior across ES6 (regular JavaScript classes), CoffeeScript classes,
and TypeScript classes. They work by running the same tests in all
environments and comparing the results.

Rather than use `act` or `waitFor` in these, I've changed them to use
`flushSync` instead so that they can flush synchronously. The reason is
that CoffeeScript doesn't have async/await, so we'd have to write those
tests differently than how they are written in the corresponding
modules. Since none of these tests cover any concurrent behavior, I
believe it's fine in this case to do everything synchronously; they
don't use any concurrent features, anyway, so effectively it's just
skipping a microtask.
2023-03-07 10:14:41 -05:00
Rubén Norte 8f812e75d6
Refactor ReactFabricHostComponent (#26323)
## Summary

This is a small refactor of `ReactFabricHostComponent` to remove
unnecessary dependencies, unused methods and type definitions to
simplify a larger refactor of the class in a following PR
(https://github.com/facebook/react/pull/26321).

## How did you test this change?

Existing unit tests.
2023-03-07 14:33:55 +00:00
Josh Story 978fae4b4f
[Float][Fiber] implement a faster hydration match for hoistable elements (#26154)
This PR is now based on #26256 

The original matching function for `hydrateHoistable` some challenging
time complexity since we built up the list of matchable nodes for each
link of that type and then had to check to exclusion. This new
implementation aims to improve the complexity

For hoisted title tags we match the first title if it is valid (not in
SVG context and does not have `itemprop`, the two ways you opt out of
hoisting when rendering titles). This path is much faster than others
and we use it because valid Documents only have 1 title anyway and if we
did have a mismatch the rendered title still ends up as the
Document.title so there is no functional degradation for misses.

For hoisted link and meta tags we track all potentially hydratable
Elements of this type in a cache per Document. The cache is refreshed
once each commit if and only if there is a title or meta hoistable
hydrating. The caches are partitioned by a natural key for each type
(href for link and content for meta). Then secondary attributes are
checked to see if the potential match is matchable.

For link we check `rel`, `title`, and `crossorigin`. These should
provide enough entropy that we never have collisions except is contrived
cases and even then it should not affect functionality of the page. This
should also be tolerant of links being injected in arbitrary places in
the Document by 3rd party scripts and browser extensions

For meta we check `name`, `property`, `http-equiv`, and `charset`. These
should provide enough entropy that we don't have meaningful collisions.
It is concievable with og tags that there may be true duplciates `<meta
property="og:image:size:height" content="100" />` but even if we did
bind to the wrong instance meta tags are typically only read from SSR by
bots and rarely inserted by 3rd parties so an adverse functional outcome
is not expected.
2023-03-06 19:52:35 -08:00
Josh Story 8a9f82ed58
[Float][Fizz][Fiber] - Do not hoist elements with `itemProp` & hydrate more tolerantly in hoist contexts (#26256)
## Do not hoist elements with `itemProp`
In HTML `itemprop` signifies a property of an `itemscope` with respect
to the Microdata spec
(https://html.spec.whatwg.org/multipage/microdata.html#microdata)

additionally `itemprop` is valid on any tag and can even make some tags
that are otherwise invalid in the `<body>` valid there (`<meta>` for
instance).

Originally I tried an approach where if you rendered something otherwise
hoistable inside an `itemscope` it would not hoist if it had an
`itemprop`. This meant that some components with `itemprop` could hoist
(if they were not scoped, which is generally invalid microdata
implementation). However the problem is things that do hoist, hoist into
the head and body and these tags can have an `itemscope`. This creates a
ton of ambiguity when trying to hydrate in these hoist scopes because we
can't know for certain whether a DOM node we find there was hoisted or
not even if it has an `itemprop` attribute. There are other scenarios
too that have abiguous semantics like rendering a hoistable with
`itemProp` outside of `<html itemScope={true>`. Is it fair to embed that
hoistable inside that itemScope even though it was defined outside?

To simplify the situation and disambiguate I dropped the `itemscope`
portion from the implementation and now any host component that could
normally be hoisted will not hoist if it has an `itemProp` prop.

In addition to the changes made for `itemProp` this PR also modifies
part of the hydration implementation to be more tolerant of tags
injected by 3rd parties. This was opportunistically done when we needed
to have context information like `inItemScope` but with the most recent
implementation that has been removed. I have however left the hydration
changes in place as it is a goal to make React handle hydrating the
entire Document even when we cannot control whether 3rd parties are
going to inject tags that React will not render but are also not
hoistables

-------

##### Original Description when we considered tracking itemScope
>One recent decision was to make elements using the `itemProp` prop not
hoistable if they were inside and itemScope. This better fits with
Microdata spec which allows for meta tags and other tag types usually
reserved for the `<head>` to be used in the `<body>` when using
itemScope.
>
>To implement this a number of small changes were necessary
>
>1. HostContext in prod needed to expand beyond just tracking the
element namespace for new element creation. It now tracks whether we are
in an itemScope. To keep this efficient it is modeled as a bitmask.
>2. To disambiguate what is and is not a potential instance in the DOM
for hoistables the hydration algo was updated to skip past non-matching
instances while attempting to claim the instance rather than ahead of
time (getNextHydratable).
>3. React will not consider an itemScope on `<html>`, `<head>`, or
`<body>` as a valid scope for the hoisting opt-out. This is important as
an invariant so we can make assumptions about certain tags in these
scopes. This should not be a functional breaking change because if any
of these tags have an `itemScope` then it can just be moved into the
first node inside the `<body>`
>
>Since we were already updating the logic for hydration to better
support `itemScope` opt-out I also changed the hydration behavior for
suspected 3rd party nodes in `<head>` and `<body>`. Now if you are
hydrating in either of those contexts hydration will skip past any
non-matching nodes until it finds a match. This allows 3rd party scripts
and extensions to inject nodes in either context that React does not
expect and still avoid a hydration mismatch.
>
>This new algorithm isn't perfect and it is possible for a mismatch to
occur. The most glaring case may be if a 3rd party script prepends a
`<div>` into `<body>` and you render a `<div>` in `<body>` in your app.
there is nothing to signal to React that this div was 3rd party so it
will claim is as the hydrated instance and hydration will almost
certainly fail immediately afterwards.
>
>The expectation is that this is rare and that if falling back to client
rendering is transparent to the user then there is not problem here. We
will continue to evaluate this and may change the hydration matching
algorithm further to match user and developer expectations
2023-03-06 15:00:54 -08:00
Jan Kassens 3cad3a54ed
Use content hash for facebook-www builds (#26331)
Currently, any commit to React causes an internal sync since the Git
commit hash is part of the build. This creates a lot more sync commits
and noise than necessary, see:
https://github.com/facebook/react/commits/builds/facebook-www

This PR changes the version string to be a hash of the target build
files instead. This way we get a new version with any change that
actually impacts the generated files and still have a matching version
across the files.
2023-03-06 17:13:17 -05:00
Jan Kassens ba353a50a6
Build: make version in build artifacts match (#26329)
Some build artifacts contain multiple version strings. It seems like an
oversight to me that this `.replace` call just replaces the one that
happens to be first.
2023-03-06 15:38:43 -05:00
Jan Kassens 88313ffd57
Codesandbox: upgrade to Node.js 18 (#26330)
Turns out Codesandbox didn't support `String.prototype.replaceAll` in
#26329.

This updates the config to use Node.js 18 for Codesandbox builds.
2023-03-06 15:38:03 -05:00
Andrew Clark 6e1756a5a9
Move suspended render logic to ensureRootIsScheduled (#26328)
When the work loop is suspended, we shouldn't schedule a new render task
until the promise has resolved. When I originally implemented this, I
wasn't sure where to put this logic — `ensureRootIsScheduled` is the
more natural place for it, but that's also a really hot path, so I chose
to do it elsewhere, and left a TODO to reconsider later.

Now it's later. I'm working on a refactor to move the
`ensureRootIsScheduled` call to always happen in a microtask, so that if
there are multiple updates/pings in a single event, they get batched
into a single operation. Which means I can put the logic in that
function where it belongs.
2023-03-06 12:27:48 -05:00
Andrew Clark 1528c5ccdf
SchedulerMock.unstable_yieldValue -> SchedulerMock.log (#26312)
(This only affects our own internal repo; it's not a public API.)

I think most of us agree this is a less confusing name. It's possible
someone will confuse it with `console.log`. If that becomes a problem we
can warn in dev or something.
2023-03-06 11:09:07 -05:00
Jan Kassens 4bbac04cd3
Upgrade Flow to 0.201 (#26326)
Small Flow upgrade to keep us current.
2023-03-06 10:33:22 -05:00
Rubén Norte eb616a12f1
Extract duplicated methods in Fabric and the legacy renderer to a shared module (#26319)
## Summary

The following methods have exactly the same implementation on Fabric and
the legacy renderer:
* `findHostInstance_DEPRECATED`
* `findNodeHandle`
* `dispatchCommand`
* `sendAccessibilityEvent`

This just extracts those functions to a common module so they're easier
to change (no need to sync changes in 2 files).

## How did you test this change?

Existing tests (this is a refactor).
2023-03-06 10:51:59 +00:00
Andrew Clark 49f7410467
Fix: Infinite act loop caused by wrong shouldYield (#26317)
Based on a bug report from @bvaughn.

`act` should not consult `shouldYield` when it's performing work,
because in a unit testing environment, I/O (such as `setTimeout`) is
likely mocked. So the result of `shouldYield` can't be trusted.

In the regression test, I simulate the bug by mocking `shouldYield` to
always return `true`. This causes an infinite loop in `act`, because it
will keep trying to render and React will keep yielding.
2023-03-05 20:24:39 -05:00
Sebastian Markbåge 106ea1c584
Support Iterables in Flight (#26313)
We support any super type of anything that we can serialize. Meaning
that as long as the Type that's passed through is less precise, it means
that we can encoded it as any subtype and therefore the incoming type
doesn't have to be the subtype in that case. Basically, as long as
you're only passing through an `Iterable<T>` in TypeScript, then you can
pass any `Iterable<T>` and we'll treat it as an array.

For example we support Promises *and* Thenables but both are encoded as
Promises.

We support Arrays and since Arrays are also Iterables, we can support
Iterables.

For @wongmjane
2023-03-05 13:18:54 -05:00
Hendrik Liebau f905da2276
[Flight] Send server reference error chunks to the client (#26293)
Previously when a called server reference function was rejected, the
emitted error chunk was not flushed, and the request was not properly
closed.

Co-authored-by: Sebastian Markbage <sebastian@calyptus.eu>
2023-03-04 22:56:19 -05:00
Sebastian Markbåge e0241b6600
Simplify Webpack References by encoding file path + export name as single id (#26300)
We always look up these references in a map so it doesn't matter what
their value is. It could be a hash for example.

The loaders now encode a single $$id instead of filepath + name.

This changes the react-client-manifest to have a single level. The value
inside the map is still split into module id + export name because
that's what gets looked up in webpack.

The react-ssr-manifest is still two levels because that's a reverse
lookup.
2023-03-04 19:51:34 -05:00
Andrew Clark 25685d8a90
Codemod tests to waitFor pattern (9/?) (#26309)
This converts some of our test suite to use the `waitFor` test pattern,
instead of the `expect(Scheduler).toFlushAndYield` pattern. Most of
these changes are automated with jscodeshift, with some slight manual
cleanup in certain cases.

See #26285 for full context.
2023-03-04 18:06:20 -05:00
Andrew Clark 64dde70827
Codemod tests to waitFor pattern (8/?) (#26308)
This converts some of our test suite to use the `waitFor` test pattern,
instead of the `expect(Scheduler).toFlushAndYield` pattern. Most of
these changes are automated with jscodeshift, with some slight manual
cleanup in certain cases.

See #26285 for full context.
2023-03-04 18:04:43 -05:00
Andrew Clark 3cb5afb82e
Codemod tests to waitFor pattern (7/?) (#26307)
This converts some of our test suite to use the `waitFor` test pattern,
instead of the `expect(Scheduler).toFlushAndYield` pattern. Most of
these changes are automated with jscodeshift, with some slight manual
cleanup in certain cases.

See #26285 for full context.
2023-03-04 18:03:24 -05:00
Andrew Clark e98695db91
Codemod tests to waitFor pattern (6/?) (#26305)
This converts some of our test suite to use the `waitFor` test pattern,
instead of the `expect(Scheduler).toFlushAndYield` pattern. Most of
these changes are automated with jscodeshift, with some slight manual
cleanup in certain cases.

See #26285 for full context.
2023-03-04 11:45:26 -05:00
Andrew Clark 9a52cc8bcd
Convert ReactLazy-test to waitFor pattern (#26304)
I'm in the process of codemodding our test suite to the waitFor pattern.
See #26285 for full context.

This module required a lot of manual changes so I'm doing it as its own
PR. The reason is that most of the tests involved simulating an async
import by wrapping them in `Promise.resolve()`, which means they would
immediately resolve the next time the microtask queue was flushed. I
rewrote the tests to resolve the simulated import explicitly.

While converting these tests, I also realized that the `waitFor` helpers
weren't properly waiting for the entire microtask queue to recursively
finish — if a microtask schedules another microtask, the subsequent one
wouldn't fire until after `waitFor` had resolved. To fix this, I used
the same strategy as `act` — wait for a real task to finish before
proceeding, such as a message event.
2023-03-04 11:44:41 -05:00
mofeiZ 03462cfc7a
[Fizz] External runtime: fix bug in processing existing elements (#26303)
## Summary
Fix bug in how the Fizz external runtime processes existing template
elements.

Bug:
- getElementsByTagName returns a HTMLCollection, which is live.
- while iterating over an HTMLCollection, we call handleNode which
removes nodes

Fix:
- Call Array.from to copy children of `document.body` before processing.
- We could use `querySelectorAll` instead, but that is likely slower due
to reading more nodes.

## How did you test this change?

Did ad-hoc testing on Facebook home page by commenting out the mutation
observer and adding the following.
```javascript
  window.addEventListener('DOMContentLoaded', function () {
    handleExistingNodes(document.body);
  });
```
2023-03-04 11:26:59 -05:00
Andrew Clark faacefb4d0
Codemod tests to waitFor pattern (4/?) (#26302)
This converts some of our test suite to use the `waitFor` test pattern,
instead of the `expect(Scheduler).toFlushAndYield` pattern. Most of
these changes are automated with jscodeshift, with some slight manual
cleanup in certain cases.

See #26285 for full context.
2023-03-03 21:24:22 -05:00
Rubén Norte 06460b6fb5
Remove unnecessary (and incorrect) code for compatibility with Paper in the Fabric version of GlobalResponderHandler (#26290)
## Summary

I'm working on a refactor of the definition of `Instance` in Fabric and
I came across this code that seemed to be for compatibility with Paper,
but that it would actually throw an error in that case.

In Paper, `stateNode` is an instance of `ReactNativeFiberHostComponent`,
which doesn't have a `canonical` field. We try to access nested
properties in that field in a couple of places here, which would throw a
type error (cannot read property `_nativeTag` of `undefined`) if we
actually happened to pass a reference to a Paper state node.

In this line:

```javascript
const isFabric = !!(
      fromOrToStateNode && fromOrToStateNode.canonical._internalInstanceHandle
    );
```

If it wasn't Fabric, `fromOrToStateNode.canonical` would be undefined,
and we don't check for that before accessing
`fromOrToStateNode.canonical._internalInstanceHandle`. This means that
we actually never use this logic in Paper or we would've seen the error.

## How did you test this change?

Existing tests.
2023-03-03 23:39:04 +00:00
Andrew Clark e64a8f4035
Codemod tests to waitFor pattern (3/?) (#26299)
This converts some of our test suite to use the `waitFor` test pattern,
instead of the `expect(Scheduler).toFlushAndYield` pattern. Most of
these changes are automated with jscodeshift, with some slight manual
cleanup in certain cases.

See #26285 for full context.
2023-03-03 17:02:12 -05:00
Andrew Clark ce8a72fd4e
Codemod tests to waitFor pattern (2/?) (#26296)
This converts some of our test suite to use the `waitFor` test pattern,
instead of the `expect(Scheduler).toFlushAndYield` pattern. Most of
these changes are automated with jscodeshift, with some slight manual
cleanup in certain cases.

See #26285 for full context.
2023-03-03 17:01:57 -05:00
Josh Story 1f1f8eb559
[Float][Fizz][Fiber]: Refactor <style> Resource implementation to group on flush (#26280)
There is a problem with <style> as resource. For css-in-js libs there
may be an very large number of these hoistables being created. The
number of style tags can grow quickly and to help reduce the prevalence
of this FIzz now aggregates all style tags for a given precedence into a
single tag. The client can 'hydrate' against these compound tags but
currently on the client insertions are done individually.

additionally drops the implementation where style tags are embedding in
a template for one where `media="not all"` is set. The idea is to have
the browser construct the underlying stylesheet eagerly which does not
happen if the tag is embedded in a template

Key Decision:
One choice made in this PR is that we flush style tags eagerly even if a
boundary is blocked that is the only thing that depends on that style
rule. The reason we are starting with this implementation is that it
allows a very condensed representation of the style resources. If we
tracked which rules were used in which boundaries we would need a style
resource for every rendered <style> tag. This could be problematic for
css-in-js libs that might render hundreds or thousands of style tags.
The tradeoff here is we slightly delay content reveal in some cases (we
send extra bytes) but we have fewer DOM tags and faster SSR runtime
2023-03-03 12:50:35 -08:00
Andrew Clark 5c633a48f9
Add back accidentally deleted test comments (#26294)
The codemod I used in #26288 accidentally caused some comments to be
deleted. Because not all affected lines included comments, I didn't
notice until after landing.

This adds the comments back.
2023-03-03 14:34:41 -05:00
Mengdi Chen b073104c26
[DevTools] improve troubleshooting in README (#26235)
## Summary

Improve the README when the elements are not loaded due to Chrome
service worker malfunction
2023-03-03 14:02:21 -05:00
Mengdi Chen fcf2187919
[DevTools] Remove renderer.js from extension build (#26234)
## Summary

When looking into the compiled code of `installHook.js` of the extension
build, I noticed that it actually includes the large `attach` function
(from renderer.js). I don't think it was expected.
This is because `hook.js` imports from `backend/console.js` which
imports from `backend/renderer.js` for `getInternalReactConstants`
A straightforward way is to extract function
`getInternalReactConstants`. However, I think it's more simplified to
just merge these two files and save the 361K renderer.js from the
extension build since we have always been loading this code anyways.
I changed the execution check from `__REACT_DEVTOOLS_ATTACH__ ` to the
session storage.

## How did you test this change?

Everything works normal in my local build.
2023-03-03 14:01:58 -05:00
Rubén Norte b72ed698fb
Fixed incorrect value returned as public instance from reconciler (#26283)
## Summary

A few methods in `ReactFiberReconciler` are supposed to return
`PublicInstance` values, but they return the `stateNode` from the fiber
directly. This assumes that the `stateNode` always matches the public
instance (which it does on Web) but that's not the case in React Native,
where the public instance is a field in that object.

This hasn't caused issues because everywhere where we use that method in
React Native we actually extract the real public instance from this
"fake" public instance.

This PR fixes the inconsistency and cleans up some code.

## How did you test this change?

Existing tests.
2023-03-03 09:38:08 +00:00
Andrew Clark 25a8b9735c
Codemod tests to waitFor pattern (1/?) (#26288)
This converts some of our test suite to use the `waitFor` test pattern,
instead of the `expect(Scheduler).toFlushAndYield` pattern. Most of
these changes are automated with jscodeshift, with some slight manual
cleanup in certain cases.

See #26285 for full context.
2023-03-02 22:34:58 -05:00
Andrew Clark e524467338
New internal testing helpers: waitFor, waitForAll, waitForPaint (#26285)
Over the years, we've gradually aligned on a set of best practices for
for testing concurrent React features in this repo. The default in most
cases is to use `act`, the same as you would do when testing a real
React app. However, because we're testing React itself, as opposed to an
app that uses React, our internal tests sometimes need to make
assertions on intermediate states that `act` intentionally disallows.

For those cases, we built a custom set of Jest assertion matchers that
provide greater control over the concurrent work queue. It works by
mocking the Scheduler package. (When we eventually migrate to using
native postTask, it would probably work by stubbing that instead.)

A problem with these helpers that we recently discovered is, because
they are synchronous function calls, they aren't sufficient if the work
you need to flush is scheduled in a microtask — we don't control the
microtask queue, and can't mock it.

`act` addresses this problem by encouraging you to await the result of
the `act` call. (It's not currently required to await, but in future
versions of React it likely will be.) It will then continue flushing
work until both the microtask queue and the Scheduler queue is
exhausted.

We can follow a similar strategy for our custom test helpers, by
replacing the current set of synchronous helpers with a corresponding
set of async ones:

- `expect(Scheduler).toFlushAndYield(log)` -> `await waitForAll(log)`
- `expect(Scheduler).toFlushAndYieldThrough(log)` -> `await
waitFor(log)`
- `expect(Scheduler).toFlushUntilNextPaint(log)` -> `await
waitForPaint(log)`

These APIs are inspired by the existing best practice for writing e2e
React tests. Rather than mock all task queues, in an e2e test you set up
a timer loop and wait for the UI to match an expecte condition. Although
we are mocking _some_ of the task queues in our tests, the general
principle still holds: it makes it less likely that our tests will
diverge from real world behavior in an actual browser.

In this commit, I've implemented the new testing helpers and converted
one of the Suspense tests to use them. In subsequent steps, I'll codemod
the rest of our test suite.
2023-03-02 21:58:11 -05:00
Rubén Norte d49e0e0be0
Removed unused imperative events implementation from React Native renderer (#26282)
## Summary

I'm going to start implementing parts of this proposal
https://github.com/react-native-community/discussions-and-proposals/pull/607

As part of that implementation I'm going to refactor a few parts of the
interface between React and React Native. One of the main problems we
have right now is that we have private parts used by React and React
Native in the public instance exported by refs. I want to properly
separate that.

I saw that a few methods to attach event handlers imperatively on refs
were also exposing some things in the public instance (the
`_eventListeners`). I checked and these methods are unused, so we can
just clean them up instead of having to refactor them too. Adding
support for imperative event listeners is in the roadmap after this
proposal, and its implementation might differ after this refactor.

This is essentially a manual revert of #23386.

I'll submit more PRs after this for the rest of the refactor.

## How did you test this change?

Existing jest tests. Will test a React sync internally at Meta.
2023-03-02 15:54:51 +00:00
Andrew Clark 41110021f2
Fix: Selective hydration causing incorrect thenable type passed to DevTools (#26275)
Selective hydration is implemented by suspending the current render
using a special internal opaque object. This is conceptually similar to
suspending with a thenable in userspace, but the opaque object should
not leak outside of the reconciler.

We were accidentally passing this object to DevTool's
markComponentSuspended function, which expects an actual thenable. This
happens in the error handling path (handleThrow).

The fix is to check for the exception reason before calling
markComponentSuspended. There was already a naive check in place, but it
didn't account for all possible enum values of the exception reason.
2023-03-01 11:38:48 -05:00
Sebastian Markbåge 67a61d5bd7
[Flight Fixture] Show SSR Support with CSS (#26263)
Builds on #26257.

To do this we need access to a manifest for which scripts and CSS are
used for each "page" (entrypoint).

The initial script to bootstrap the app is inserted with
`bootstrapScripts`. Subsequent content are loaded using the chunks
mechanism built-in.

The stylesheets for each pages are prepended to each RSC payload and
rendered using Float. This doesn't yet support styles imported in
components that are also SSR:ed nor imported through Server Components.
That's more complex and not implemented in the node loader.

HMR doesn't work after reloads right now because the SSR renderer isn't
hot reloaded because there's no idiomatic way to hot reload ESM modules
in Node.js yet. Without killing the HMR server. This leads to hydration
mismatches when reloading the page after a hot reload.

Notably this doesn't show serializing the stream through the HTML like
real implementations do. This will lead to possible hydration mismatches
based on the data. However, manually serializing the stream as a string
isn't exactly correct due to binary data. It's not the idiomatic way
this is supposed to work. This will all be built-in which will make this
automatic in the future.
2023-02-28 19:44:37 -05:00
Sebastian Markbåge 40755c01a6
[Flight Fixture] Proxy requests through the global server instead of directly (#26257)
This proxies requests through the global server instead of requesting
RSC responses from the regional server. This is a bit closer to
idiomatic, and closer to SSR.

This also wires up HMR using the Middleware technique instead of server.
This will be an important part of RSC compatibility because there will
be a `react-refresh` aspect to the integration.

This convention uses `Accept` header to branch a URL between HTML/RSC
but it could be anything really. Special headers, URLs etc. We might be
more opinionated about this in the future but now it's up to the router.

Some fixes for Node 16/17 support in the loader and fetch polyfill.
2023-02-28 19:24:16 -05:00
Jiachi Liu 38509cce9b
Add preconnect and prefetchDNS to rendering-stub (#26265)
<!--
  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

Adding `preconnect` and `prefetchDNS` to rendering-stub build

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

## 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.
-->
2023-02-28 17:27:16 -05:00
Jan Kassens b2ae9ddb3b
Cleanup enableSyncDefaultUpdate flag (#26236)
This feature flag is enabled everywhere.
2023-02-27 14:04:02 -05:00
Josh Story 6ff1733e63
[Float][Fizz][Fiber] support type for ReactDOM.preload() options (#26239)
preloads often need to come with a type attribute which allows browsers
to decide if they support the preloading resource's type. If the type is
unsupported the preload will not be fetched by the Browser. This change
adds support for `type` in `ReactDOM.preload()` as a string option.
2023-02-25 11:06:09 -08:00
Josh Story 1173a17e6e
[Float][Fizz][Fiber] implement preconnect and prefetchDNS float methods (#26237)
Adds two new ReactDOM methods

### `ReactDOM.prefetchDNS(href: string)`
In SSR this method will cause a `<link rel="dns-prefetch" href="..." />`
to flush before most other content both on intial flush (Shell) and late
flushes. It will only emit one link per href.

On the client, this method will case the same kind of link to be
inserted into the document immediately (when called during render, not
during commit) if there is not already a matching element in the
document.

### `ReactDOM.preconnect(href: string, options?: { crossOrigin?: string
})`
In SSR this method will cause a `<link rel="dns-prefetch" href="..."
[corssorigin="..."] />` to flush before most other content both on
intial flush (Shell) and late flushes. It will only emit one link per
href + crossorigin combo.

On the client, this method will case the same kind of link to be
inserted into the document immediately (when called during render, not
during commit) if there is not already a matching element in the
document.
2023-02-25 11:04:51 -08:00
Sebastian Markbåge e7d7d4cb4b
Move Flight Fixture to use Middleware instead of WebDevServer (#26246)
This lets us put it in the same server that would be serving this
content in a more real world scenario.

I also de-CRA:ified this a bit by simplifying pieces we don't need.

I have more refactors coming for the SSR pieces but since many are
eyeing these fixtures right now I figured I'd push earlier.

The design here is that there are two servers:

- Global - representing a "CDN" which will also include the SSR server.
- Regional - representing something close to the data with low waterfall
costs which include the RSC server.

This is just an example.

These are using the "unbundled" strategy for the RSC server just to show
a simple case, but an implementation can use a bundled SSR server.

A smart SSR bundler could also put RSC and SSR in the same server and
even the same JS environment. It just need to ensure that the module
graphs are kept separately - so that the `react-server` condition is
respected. This include `react` itself. React will start breaking if
this isn't respected because the runtime will get the wrong copy of
`react`. Technically, you don't need the *entire* module graph to be
separated. It just needs to be any part of the graph that depends on a
fork. Like if "Client A" -> "foo" and "Server B" -> "foo", then it's ok
for the module "foo" to be shared. However if "foo" -> "bar", and "bar"
is forked by the "react-server" condition, then "foo" also needs to be
duplicated in the module graph so that it can get two copies of "bar".
2023-02-25 12:10:39 -05:00
Mengdi Chen 564166099b
[DevTools] remove script tag immediately (#26233)
Fixes https://github.com/facebook/react/issues/25924 for React DevTools
specifically.

## Summary

If we remove the script after it's loaded, it creates a race condition
with other code. If some other code is searching for the first script
tag or first element of the document, this might broke it.

## How did you test this change?

I've tested in my local build that even if we remove the script tag
immediately, the code is still correctly executed.
2023-02-24 15:13:05 -05:00
Sophie Alpert a8f971b7a6
Switch to mount dispatcher after use() when needed (#26232)
When resuming a suspended render, there may be more Hooks to be called
that weren't seen the previous time through. Make sure to switch to the
mount dispatcher when calling use() if the next Hook call should be
treated as a mount.

Fixes #25964.
2023-02-24 12:06:27 -08:00
Sophie Alpert 96cdeaf89b
[Fizz Node] Fix null bytes written at text chunk boundaries (#26228)
We encode strings 2048 UTF-8 bytes at a time. If the string we are
encoding crosses to the next chunk but the current chunk doesn't fit an
integral number of characters, we need to make sure not to send the
whole buffer, only the bytes that are actually meaningful.

Fixes #24985. I was able to verify that this fixes the repro shared in
the issue (be careful when testing because the null bytes do not show
when printed to my terminal, at least). However, I don't see a clear way
to add a test for this that will be resilient to small changes in how we
encode the markup (since it depends on where specific multibyte
characters fall against the 2048-byte boundaries).
2023-02-24 11:33:54 -08:00
Mengdi Chen ca2cf319fd
[DevTools] permanently polyfill for rAF in devtools_page (#26193)
## Summary

We had this as a temporary fix for #24626. Now that Chrome team decides
to turn the flag on again (with good reasons explained in
https://bugs.chromium.org/p/chromium/issues/detail?id=1241986#c31), we
will turn it into a long term solution.
In the future, we want to explore whether we can render React elements
on panel.html instead, as `requestAnimationFrame` produces higher
quality animation.

## How did you test this change?

Tested on local build with "Throttle non-visible cross-origin iframes"
flag enabled.
2023-02-23 16:53:11 -05:00
lauren bfb9cbd8ca
[difftrain] Make github sha clickable for easier debugging (#26225) 2023-02-23 07:59:22 -08:00
Andrew Clark c04b180701
Remove eventTime field from class Update type (#26219)
`eventTime` is a vestigial field that can be cleaned up. It was
originally used as part of the starvation mechanism but it's since been
replaced by a per-lane field on the root.

This is a part of a series of smaller refactors I'm doing to
simplify/speed up the `setState` path, related to the Sync Unification
project that @tyao1 has been working on.
2023-02-22 15:32:09 -05:00
Abhiram Satpute 212b89fa25
Bug: yarn flow dom does not exist, so console should suggest yarn flow dom-node (#26213)
<!--
  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
The `yarn flow` command, as suggested for every PR Submission (Task No.
9), tells us `The yarn flow command now requires you to pick a primary
renderer` and provides a list for the same. However, in at the bottom of
the prompt, it suggests `If you are not sure, run yarn flow dom`. This
command `yarn flow dom` does not exist in the list and thus the command
does nothing and exits with `status code 1` without any flow test.

<!--
Explain the **motivation** for making this change. What existing problem
does the pull request solve?
-->
While trying to submit a different PR for code cleaning, just during
submission I read the PR Guidelines, and while doing `yarn test`, `yarn
lint`, and `yarn flow`, I came across this issue and thought of
submitting a PR for the same.

## How did you test this change?
Since this code change does not change any logic, just the text
information, I only ran `yarn linc` and `yarn test` for the same.

<!--
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.
-->
Here is how the issue currently looks like:

![facebook yarn flow
dom](https://user-images.githubusercontent.com/20269286/220337686-b8a9b786-92e0-4c66-88a9-e94bfbed6edf.JPG)

Signed-off-by: abhiram11 <abhiramsatpute@gmail.com>
Co-authored-by: abhiram11 <abhiramsatpute@gmail.com>
2023-02-21 21:30:34 +01:00
Sebastian Markbåge 0a76fb9ec4
Copy from build to node_modules instead of linking to builds (#26210)
Using the `link:` protocol to create a dependency doesn't work when we
edit the `package.json` to lock the version to a specific version. It
didn't really work before neither, it was just that `yarn` installed an
existing `scheduler` dependency from npm instead of using the built one.

So I'm updating all the fixture to use the technique where we copy files
instead.
2023-02-21 14:48:37 -05:00
Sebastian Markbåge c8d4eeda5f
Rename `yarn start` to `yarn dev` and `yarn start:prod` to `yarn start` (#26209)
The `start` convention is a CRA convention but nobody else of the modern
frameworks / tools use this convention for a file watcher and dev mode.
Instead the common convention is `dev`. Instead `start` is for running a
production build that's already been built.

---------

Co-authored-by: Sebastian Silbermann <silbermann.sebastian@gmail.com>
2023-02-21 14:18:21 -05:00
Sebastian Markbåge 60144a04da
Split out Edge and Node implementations of the Flight Client (#26187)
This splits out the Edge and Node implementations of Flight Client into
their own implementations. The Node implementation now takes a Node
Stream as input.

I removed the bundler config from the Browser variant because you're
never supposed to use that in the browser since it's only for SSR.
Similarly, it's required on the server. This also enables generating a
SSR manifest from the Webpack plugin. This is necessary for SSR so that
you can reverse look up what a client module is called on the server.

I also removed the option to pass a callServer from the server. We might
want to add it back in the future but basically, we don't recommend
calling Server Functions from render for initial render because if that
happened client-side it would be a client-side waterfall. If it's never
called in initial render, then it also shouldn't ever happen during SSR.
This might be considered too restrictive.

~This also compiles the unbundled packages as ESM. This isn't strictly
necessary because we only need access to dynamic import to load the
modules but we don't have any other build options that leave
`import(...)` intact, and seems appropriate that this would also be an
ESM module.~ Went with `import(...)` in CJS instead.
2023-02-21 13:18:24 -05:00
mofeiZ 70b0bbda76
[fizz][external-runtime] Fix: process mutation records before disconnecting (#26169)
> All notifications of mutations that have already been detected, but
not yet reported to the observer, are discarded. To hold on to and
handle the detected but unreported mutations, use the takeRecords()
method.
>    -- ([Mozilla docs for disconnect](

https://developer.mozilla.org/en-US/docs/Web/API/MutationObserver/disconnect))

Fizz external runtime needs to process mutation records (representing
potential Fizz instructions) before calling `disconnect()`. We currently
do not do this (and might drop some instructions).
2023-02-21 09:10:23 -08:00
Sebastian Silbermann c7967b194b
Distribute bundles more evenly into CI shards (#26208)
## Summary

Previously, we distributed bundles into shards and then checked if we
need to actually build that bundle. This can under-utilize shards
heavily (e.g.
https://app.circleci.com/pipelines/github/facebook/react/38611/workflows/df9e56e7-d476-49ee-9392-d8b37c81aa66/jobs/630545/parallel-runs/28?filterBy=ALL
only building a single bundle).

This won't result in an optimal distribution but, if we're lucky, we
might end up with shard #26 not taking 7mins anymore. The slowest shard
ultimately decicdes when we can start with testing builds.

## How did you test this change?

- [x] `CIRCLE_NODE_INDEX=28 CIRCLE_NODE_TOTAL=40 yarn build` building
more than 1 bundle
- [x] Check timings of `yarn_build` so that we don't up with an
over-stuffed shard (e.g. a shard having to build all the expensive
bundles). Casually dropping 60min idle time 🎉:
- Before:
https://app.circleci.com/pipelines/github/facebook/react/38683/workflows/a41533d7-811c-439d-9751-214ba06035c5/jobs/632230/timing
- After:
https://app.circleci.com/pipelines/github/facebook/react/38686/workflows/8a770df6-5b3e-41ea-b3b5-10abeae703e7/jobs/632247/timing
2023-02-20 22:16:23 +01:00
Sebastian Silbermann bb1e3d0e19
Fail yarn build if any bundle fails to build (#26207)
## Summary

`yarn build` would previously still exit with zero exit code hiding
build errors such as
https://app.circleci.com/pipelines/github/facebook/react/38609/workflows/62a73635-3bf3-4264-8c48-a61844a27764/jobs/630503/parallel-runs/11?filterBy=ALL&invite=true#step-105-17.
These issues are still surfaced due to missing size bot artifacts but
the overall PR status would still be green which we don't want.

Now we just exit with the same exit has a the process of a single build
if it's non-zero.

## How did you test this change?

- [x] fails based on the parent of
62e6c4612ec704cf07c99b318bc8f26d3ec3f588:
https://app.circleci.com/pipelines/github/facebook/react/38681/workflows/654c68ed-cebc-48d4-a156-bac719772f6f/jobs/632166
- [x] passes based on `main`
2023-02-20 21:59:21 +01:00
Sebastian Markbåge 62e6c4612e
Move Mutation/Persistence fork inline into the functions (#26206)
We should never use any logic beyond declarations in the module scope,
including conditions, because in a cycle that can lead to problems.

More importantly, the compiler can't safely reorder statements between
these points which limits the optimizations we can do.
2023-02-20 15:03:22 -05:00
Sebastian Markbåge 80cf4a099e
Update Closure Compiler (#26205)
I need it for https://github.com/facebook/react/pull/26187.

We need to specify specifically the output mode `ECMASCRIPT5_STRICT` to
remove `const` from the Fizz runtime.
2023-02-20 13:27:13 -05:00
Samuel Susla 2cc54b57ed
Change commit message for DiffTrain commigs (#26203)
Previously, the commit message looked something like this in Github: 
<img width="921" alt="Screenshot 2023-02-20 at 13 52 35"
src="https://user-images.githubusercontent.com/1733610/220126265-d77931e0-18ac-46a0-bf23-d868f8af17a9.png">

With this change, it will look like:

DiffTrain build for commit db5e6250d4.
2023-02-20 15:17:44 +00:00
chenpeng 8a82207286
add test case for semver major comparisons 2023-02-20 15:36:48 +01:00
Glenn 'devalias' Grant 6b6d0617ef
Update Rollup and related plugins to their most recent versions (#24916)
Update Rollup and related plugins to their most recent versions +
resolve any breaking changes/deprecations/etc along the way. I made each
change piece by piece, so the commit history tells a pretty good story
of what was changed where/how/why.

fixes https://github.com/facebook/react/issues/24894

For the full deepdive/context, see:

- https://github.com/facebook/react/issues/24894

The inspiration for this came from @jasonwilliams 's PR for attempting
to add sourcemap output support to React's builds:

- https://github.com/facebook/react/issues/20186
  - https://github.com/facebook/react/pull/21946

But I figured that it would be useful to minimise the scope of changes
in that PR, and to modernise the build tooling along the way.

If any of these updates rely on a node version later than `10.x`, then
the following PR may have to land first, otherwise things might break on
AppVeyor:

- https://github.com/facebook/react/issues/24891
  - https://github.com/facebook/react/pull/24892

Co-authored-by: Sebastian Markbage <sebastian@calyptus.eu>
2023-02-20 01:35:56 -05:00
Ming Ye bc38a3dfa7
Update rollup config to use moduleSideEffects (#26199)
## Summary

In rollup v1.19.4, The "treeshake.pureExternalModules" option is
deprecated. The "treeshake.moduleSideEffects" option should be used
instead, see
https://github.com/rollup/rollup/blob/v1.19.4/src/Graph.ts#L130.

## How did you test this change?

ci green
2023-02-20 00:04:26 -05:00
Sebastian Markbåge db5e6250d4
Rename yarn build-combined to just yarn build (#26192)
It's confusing to new contributors, and me, that you're supposed to use
`yarn build-combined` for almost everything but not fixtures.

We should use only one build command for everything.

Updated fixtures to use the folder convention of build-combined.
2023-02-17 16:00:18 -05:00
Andrew Clark c9d9f524d7
Make enableCustomElementPropertySupport a dynamic flag in www build (#26194)
Turns enableCustomElementPropertySupport into a dynamic flag in the www
build so we can turn it on behind a GK.
2023-02-17 15:45:03 -05:00
Mengdi Chen 1a49e2d833
remove flow check in electron app.js (#26184)
When we were upgrading flow in
6ddcbd4f96
we added `$FlowFixMe` for some parameters in this file. However, this
file is not compiled at all, and the `:` syntax breaks the code.

This PR removes the flow check in this file
2023-02-17 11:54:43 -05:00
BIKI DAS 4fcc9184ac
Test :Add a small test for ReactTestUtils to find rendered component with type in document (#24368)
I tried to write test for the ReactTestUtils to find rendered component
with type in document

Tests before this PR

![Windows PowerShell 4_13_2022 11_35_24
PM](https://user-images.githubusercontent.com/72331432/163243620-40eb753c-4136-4793-a628-efcf9e004562.png)


Tests after this PR 

![Windows PowerShell 4_13_2022 11_35_30
PM](https://user-images.githubusercontent.com/72331432/163244704-cd17f0e3-7289-4794-895a-be03753e46de.png)
2023-02-17 12:23:10 +01:00
Mengdi Chen 42106558ed
React DevTools 4.27.1 -> 4.27.2 (#26185) 2023-02-16 16:46:23 -05:00
lauren 21b49103d6
[difftrain] Remove dependency on node-fetch (#26182)
`fetch` is now provided by github-scripts implicitly in
https://github.com/actions/github-script/releases/tag/v6.4.0, so this
was causing a duplicate declaration error.
2023-02-16 12:47:12 -08:00
Sebastian Markbåge 189f70e17b
Create a bunch of custom webpack vs unbundled node bundles (#26172)
We currently have an awkward set up because the server can be used in
two ways. Either you can have the server code prebundled using Webpack
(what Next.js does in practice) or you can use an unbundled Node.js
server (what the reference implementation does).

The `/client` part of RSC is actually also available on the server when
it's used as a consumer for SSR. This should also be specialized
depending on if that server is Node or Edge and if it's bundled or
unbundled.

Currently we still assume Edge will always be bundled since we don't
have an interceptor for modules there.

I don't think we'll want to support this many combinations of setups for
every bundler but this might be ok for the reference implementation.

This PR doesn't actually change anything yet. It just updates the
plumbing and the entry points that are built and exposed. In follow ups
I'll fork the implementation and add more features.

---------

Co-authored-by: dan <dan.abramov@me.com>
2023-02-16 11:01:52 -05:00
Jonny Burger fbf3bc3158
Add `scale` as a unitless property (#25601)
## Summary

CSS has a new property called `scale` (`scale: 2` is a shorthand for
`transform: scale(2)`).

In vanilla JavaScript, we can do the following:

```js
document.querySelector('div').scale = 2;
```

which will make the `<div>` twice as big. So in JavaScript, it is
possible to pass a plain number.
However, in React, the following does not work currently:


```js
<div style={{scale: 2}}>
```

because `scale` is not in the list of unitless properties. This PR adds
`scale` to the list.


## How did you test this change?

I built `react` and `react-dom` from source and copied it into the
node_modules of my project and verified that now `<div style={{scale:
2}}>` does indeed work whereas before it did not.
2023-02-16 11:12:32 +01:00
BIKI DAS 2f40170192
Don't recommend deprecated debugger script (#26171)
yarn debug-test is now deprecated in React package.json. It has been
replaced by yarn test --debug.



https://user-images.githubusercontent.com/72331432/219268188-8ff5dd42-da2b-434c-83be-72a9d258ee98.mp4
2023-02-16 11:11:12 +01:00
Mateus Toledo fccf3a9fba
Remove redundant test steps (#26161)
<!--
  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 debug-test --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

This TODO mentions an issue with JSDOM that [seems to have been
resolved](https://github.com/jsdom/jsdom/pull/2996).

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

## How did you test this change?

- Ensured that the `document.activeElement` is no longer `node` after
`node.blur` is called.
- Verified that the tests still pass.
- Looked for [a merged PR that fixes the
issue](https://github.com/jsdom/jsdom/pull/2996).

<!--
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.
-->
2023-02-13 21:47:42 +01:00
Sebastian Silbermann 86c8c8db79
test: Don't retry flushActWork if flushUntilNextPaint threw (#26121)
## Summary

Fixes "ReferenceError: You are trying to access a property or method of
the Jest environment after it has been torn down." in
`ReactIncrementalErrorHandling-test.internal.js`

Alternatives:

1. Additional `await act(cb)` call where `cb` makes sure we can flush
until next paint without throwing
    ```js
    // Ensure test isn't exited with pending work
    await act(async () => {
      root.render(<App shouldThrow={false} />);
    });
    ```
1. Use `toFlushAndThrow`
    ```diff
    -    let error;
    -    try {
    -      await act(async () => {
    -        root.render(<App shouldThrow={true} />);
    -      });
    -    } catch (e) {
    -      error = e;
    -    }
    +    root.render(<App shouldThrow={true} />);
     
    -    expect(error.message).toBe('Oops!');
    +    expect(Scheduler).toFlushAndThrow('Oops!');
         expect(numberOfThrows < 100).toBe(true);
    ```

But then it still wouldn't make sense to pass `resolve` and `reject` to
the next `flushActWork`. Even if the next `flushActWork` would flush
until next paint without throwing, we couldn't resolve or reject because
we already did reject.
 

## How did you test this change?

- `yarn test --watch
packages/react-reconciler/src/__tests__/ReactIncrementalErrorHandling-test.internal.js`
produces no more errors after the test finishes.
2023-02-13 21:45:59 +01:00
Ming Ye 4a4ef2706c
Remove unnecessary flowconfig ignore paths (#26159)
## Summary

By removing them, the flowconfig file will be cleaner and easier to
maintain.

## How did you test this change?

ci green
2023-02-12 16:03:32 -05:00
Josh Story 64acd3918a
remove unguarded getRootNode call (#26152)
I forgot to guard the `getRootNode` call in #26106 and it fails in IE8
and old jsdom. I consolidated the implementation a bit and removed the
unguarded call
2023-02-10 13:35:50 -08:00
Jan Kassens 2de85d7c71
Minor Jest upgrade (#26150)
Minor version bump to get the fix for `numPassingAsserts`:
https://github.com/facebook/jest/pull/13795

Test Plan:
CI
2023-02-10 14:06:14 -05:00
Ming Ye 71cace4d32
Migrate testRunner from jasmine2 to jest-circus (#26144)
## Summary

In jest v27, jest-circus as default test runner
(https://github.com/facebook/jest/pull/10686)

## How did you test this change?

ci green
2023-02-10 13:39:14 -05:00
Sebastian Silbermann b8ae89f382
Fix and update attribute-behavior fixture (#26114)
## Summary

Due to https://github.com/facebook/react/issues/25928 the attribute
fixture could no longer finish since it expects at least something to
render. But since Fizz currently breaks down completely on malformed
`<meta>` tags, the fixture could no longer handle this.

The fixture now renders valid types for `meta` tags.

Note that the snapshot change to `viewTarget`` is already on `main`.
Review by commit helps to understand this.

Added `html[lang]` so that we test at least one standard attribute on
`<html>`. `version` is obsolete so results are not that trustworthy.

## How did you test this change?

With Chrome Version 109.0.5414.119 (Official Build) (64-bit)

- `yarn build --type=UMD_DEV react/index,react-dom && cd
fixtures/attribute-behavior && yarn install && yarn start`
2023-02-10 19:19:26 +01:00
Xin Chen d9e0485c84
Bypass packages that are already published when confirmed by users (#26141)
## Summary

I ran into some two factor certification issue and had to resume the
publish script. However, this time if I confirmed the published package,
it will still try to publish the same version and fail. This is not
expected, and it blocks me from publishing the rest of the packages.

## How did you test this change?

I re-run the publish script after the change and successfully publish
the rest of the packages.

```
? Have you run the build-and-test script? Yes

✓ Checking NPM permissions for ryancat. 881 ms

? Please provide an NPM two-factor auth token: 278924


react-devtools version 4.27.2 has already been published.

? Is this expected (will skip react-devtools@4.27.2)? Yes


react-devtools-core version 4.27.2 has already been published.

? Is this expected (will skip react-devtools-core@4.27.2)? Yes

✓ Publishing package react-devtools-inline 23.1 secs

You are now ready to publish the extension to Chrome, Edge, and Firefox:
  https://fburl.com/publish-react-devtools-extensions

When publishing to Firefox, remember the following:
  Build id: 625690
  Git archive: ******
```
2023-02-10 11:28:31 -05:00
Sebastian Markbåge c8510227c1
Treat displayName as undefined (#26148)
When we have a key we read displayName eagerly for future warnings.

In general, React should be inspecting if something is a client
reference before dotting into it. However, we use displayName a lot and
it kind of has defined meaning for debugging everywhere it's used so
seems fine to treat this as undefined.
2023-02-10 11:23:48 -05:00
Ming Ye 55542bc73d
Update jest printBasicPrototype config (#26142) 2023-02-10 09:58:57 +01:00
Josh Story 6396b66411
Model Float on Hoistables semantics (#26106)
## Hoistables

In the original implementation of Float, all hoisted elements were
treated like Resources. They had deduplication semantics and hydrated
based on a key. This made certain kinds of hoists very challenging such
as sequences of meta tags for `og:image:...` metadata. The reason is
each tag along is not dedupable based on only it's intrinsic properties.
two identical tags may need to be included and hoisted together with
preceding meta tags that describe a semantic object with a linear set of
html nodes.

It was clear that the concept of Browser Resources (stylesheets /
scripts / preloads) did not extend universally to all hositable tags
(title, meta, other links, etc...)

Additionally while Resources benefit from deduping they suffer an
inability to update because while we may have multiple rendered elements
that refer to a single Resource it isn't unambiguous which element owns
the props on the underlying resource. We could try merging props, but
that is still really hard to reason about for authors. Instead we
restrict Resource semantics to freezing the props at the time the
Resource is first constructed and warn if you attempt to render the same
Resource with different props via another rendered element or by
updating an existing element for that Resource.

This lack of updating restriction is however way more extreme than
necessary for instances that get hoisted but otherwise do not dedupe;
where there is a well defined DOM instance for each rendered element. We
should be able to update props on these instances.

Hoistable is a generalization of what Float tries to model for hoisting.
Instead of assuming every hoistable element is a Resource we now have
two distinct categories, hoistable elements and hoistable resources. As
one might guess the former has semantics that match regular Host
Components except the placement of the node is usually in the <head>.
The latter continues to behave how the original implementation of
HostResource behaved with the first iteration of Float

### Hoistable Element
On the server hoistable elements render just like regular tags except
the output is stored in special queues that can be emitted in the stream
earlier than they otherwise would be if rendered in place. This also
allow for instance the ability to render a hoistable before even
rendering the <html> tag because the queues for hoistable elements won't
flush until after we have flushed the preamble (`<DOCTYPE
html><html><head>`).

On the client, hoistable elements largely operate like HostComponents.
The most notable difference is in the hydration strategy. If we are
hydrating and encounter a hoistable element we will look for all tags in
the document that could potentially be a match and we check whether the
attributes match the props for this particular instance. We also do this
in the commit phase rather than the render phase. The reason hydration
can be done for HostComponents in render is the instance will be removed
from the document if hydration fails so mutating it in render is safe.
For hoistables the nodes are not in a hydration boundary (Root or
SuspenseBoundary at time of writing) and thus if hydration fails and we
may have an instance marked as bound to some Fiber when that Fiber never
commits. Moving the hydration matching to commit ensures we will always
succeed in pairing the hoisted DOM instance with a Fiber that has
committed.

### Hoistable Resource
On the server and client the semantics of Resources are largely the same
they just don't apply to title, meta, and most link tags anymore.
Resources hoist and dedupe via an `href` key and are ref counted. In a
future update we will add a garbage collector so we can clean up
Resources that no longer have any references

## `<style>` support
In earlier implementations there was no support for <style> tags. This
PR adds support for treating `<style href="..."
precedence="...">...</style>` as a Resource analagous to `<link
rel="stylesheet" href="..." precedence="..." />`

It may seem odd at first to require an href to get Resource semantics
for a style tag. The rationale is that these are for inlining of actual
external stylesheets as an optimization and for URI like scoping of
inline styles for css-in-js libraries. The href indicates that the key
space for `<style>` and `<link rel="stylesheet" />` Resources is shared.
and the precedence is there to allow for interleaving of both kinds of
Style resources. This is an advanced feature that we do not expect most
app developers to use directly but will be quite handy for various
styling libraries and for folks who want to inline as much as possible
once Fizz supports this feature.

## refactor notes
* HostResource Fiber type is renamed HostHoistable to reflect the
generalization of the concept
* The Resource object representation is modified to reduce hidden class
checks and to use less memory overall
* The thing that distinguishes a resource from an element is whether the
Fiber has a memoizedState. If it does, it will use resource semantics,
otherwise element semantics
* The time complexity of matching hositable elements for hydration
should be improved
2023-02-09 22:59:29 -08:00
Sebastian Markbåge ef9f6e77b8
Enable passing Server References from Server to Client (#26124)
This is the first of a series of PRs, that let you pass functions, by
reference, to the client and back. E.g. through Server Context. It's
like client references but they're opaque on the client and resolved on
the server.

To do this, for security, you must opt-in to exposing these functions to
the client using the `"use server"` directive. The `"use client"`
directive lets you enter the client from the server. The `"use server"`
directive lets you enter the server from the client.

This works by tagging those functions as Server References. We could
potentially expand this to other non-serializable or stateful objects
too like classes.

This only implements server->server CJS imports and server->server ESM
imports. We really should add a loader to the webpack plug-in for
client->server imports too. I'll leave closures as an exercise for
integrators.

You can't "call" a client reference on the server, however, you can
"call" a server reference on the client. This invokes a callback on the
Flight client options called `callServer`. This lets a router implement
calling back to the server. Effectively creating an RPC. This is using
JSON for serializing those arguments but more utils coming from
client->server serialization.
2023-02-09 19:45:05 -05:00
Sebastian Markbåge 6c75d4e009
Delete blocks fixture (#26143)
It's not really up-to-date and it's not really show casing anything we
don't have elsewhere.
2023-02-09 18:44:37 -05:00
Ming Ye 35698311de
Update jest escapeString config (#26140)
## Summary

In jest v29, snapshotFormat default to escapeString:
false(https://github.com/facebook/jest/pull/13036)

## How did you test this change?

ci green
2023-02-10 00:08:37 +01:00
Jan Kassens 6ddcbd4f96
[flow] enable LTI inference mode (#26104)
This is the next generation inference mode for Flow.
2023-02-09 17:07:39 -05:00
Rubén Norte 53b1f69ba6
Implement unstable_getBoundingClientRect in RN Fabric refs (#26137)
We're fixing the timing of layout and passive effects in React Native,
and adding support for some Web APIs so common use cases for those
effects can be implemented with the same code on React and React Native.

Let's take this example:

```javascript
function MyComponent(props) {
  const viewRef = useRef();

  useLayoutEffect(() => {
    const rect = viewRef.current?.getBoundingClientRect();
    console.log('My view is located at', rect?.toJSON());
  }, []);

  return <View ref={viewRef}>{props.children}</View>;
}
```

This could would work as expected on Web (ignoring the use of `View` and
assuming something like `div`) but not on React Native because:
1. Layout is done asynchronously in a background thread in parallel with
the execution of layout and passive effects. This is incorrect and it's
being fixed in React Native (see
afec07aca2).
2. We don't have an API to access layout information synchronously. The
existing `ref.current.measureInWindow` uses callbacks to pass the
result. That is asynchronous at the moment in Paper (the legacy renderer
in React Native), but it's actually synchronous in Fabric (the new React
Native renderer).

This fixes point 2) by adding a Web-compatible method to access layout
information (on Fabric only).

This has 2 dependencies in React Native:
1. Access to `getBoundingClientRect` in Fabric, which was added in
https://github.com/facebook/react-native/blob/main/ReactCommon/react/renderer/uimanager/UIManagerBinding.cpp#L644-
L676
2. Access to `DOMRect`, which was added in
673c7617bc
.

As next step, I'll modify the implementation of this and other methods
in Fabric to warn when they're accessed during render. We can't do this
on Web because we can't (shouldn't) modify built-in DOM APIs, but we can
do it in React Native because the refs objects are built by the
framework.
2023-02-09 18:51:47 +00:00
Sebastian Silbermann c0b0b3a9f8
Only restore Yarn caches on exact key hits (#26133)
## Summary

[Current Yarn cache size:
555MB](https://app.circleci.com/pipelines/github/facebook/react/38163/workflows/70d0149e-b0bc-44e8-b8c9-e5c744cab89b/jobs/625334?invite=true#step-102-2)
[Used Yarn cache size:
344MB](https://app.circleci.com/pipelines/github/facebook/react/38166/workflows/4825d444-1426-4321-b95b-c540e6cdc6d7/jobs/625354?invite=true#step-104-5)

When we restore a global Yarn cache that's not specific to a lockfile
entry (i.e. a fallback cache), we might restore packages that are no
longer used. When we then run yarn install, we potentially add new
packages to the cache.
For example: 
1. we bump a package version
2. lockfile changes
3. cache restore misses for exact key
4. cache restore hits a prefix (fallback) containing the older version, 
5. yarn install adds the new version to the cache

Yarn is not clearing the unused packages from the global cache. So when
we then save the cache we now retain the old and new version of a
package in the global cache even though the old version is no longer
used.
This means that the global cache grows indefinitely. Restoring the cache
isn't free so CI install times will degrade over time.

Either we
1. periodically prune the cache
2. just not restore anything unless we have an exact hit. 


The chosen tradeoff depends on the
relation of commits changing deps to commits not changing deps. 
From my experience, we change deps rarely so I opted to only restore the
cache on exact hits.

## How did you test this change?

- run on `main` has 555MB of Yarn cache:
https://app.circleci.com/pipelines/github/facebook/react/38163/workflows/70d0149e-b0bc-44e8-b8c9-e5c744cab89b/jobs/625334?invite=true#step-102-2
- run on this branch only has 334MB of Yarn cache:
https://app.circleci.com/pipelines/github/facebook/react/38166/workflows/4825d444-1426-4321-b95b-c540e6cdc6d7/jobs/625354?invite=true#step-104-5
2023-02-09 18:00:11 +01:00
Ming Ye 5940934967
Update to Jest 29 (#26088)
## Summary

- yarn.lock diff +-6249, **small pr**
- use jest-environment-jsdom by default
- uncaught error from jsdom is an error object instead of strings
- abortSignal.reason is read-only in jsdom and node,
https://developer.mozilla.org/en-US/docs/Web/API/AbortSignal/reason

## How did you test this change?

ci green

---------

Co-authored-by: Sebastian Silbermann <silbermann.sebastian@gmail.com>
2023-02-09 17:07:49 +01:00
Aravind D 28fcae062b
Add support for SVG `transformOrigin` prop (#26130)
Co-authored-by: eps1lon <silbermann.sebastian@gmail.com>
2023-02-09 13:47:50 +01:00
Sebastian Silbermann 3ff1540e9b
Prefer JSX in ReactNoop assertions (to combat out-of-memory test runs) (#26127)
## Summary

Prefer `getChildrenAsJSX` or `toMatchRenderedOutput` over `getChildren`.
Use `dangerouslyGetChildren` if you really need to (e.g. for `toBe`
assertions).

Prefer `getPendingChildrenAsJSX` over `getPendingChildren`. Use
`dangerouslyGetPendingChildren` if you really need to (e.g. for `toBe`
assertions).

`ReactNoop.getChildren` contains the fibers as non-enumerable
properties. If you pass the children to `toEqual` and have a mismatch,
Jest performance is very poor (to the point of causing out-of-memory
crashes e.g.
https://app.circleci.com/pipelines/github/facebook/react/38084/workflows/02ca0cbb-bab4-4c19-8d7d-ada814eeebb9/jobs/624297/parallel-runs/5?filterBy=ALL&invite=true#step-106-27).
Mismatches can sometimes be intended e.g. on gated tests.

Instead, I converted almost all of the `toEqual` assertions to
`toMatchRenderedOutput` assertions or compare the JSX instead. For
ReactNoopPersistent we still use `getChildren` since we have assertions
on referential equality. `toMatchRenderedOutput` is more accurate in
some instances anyway. I highlighted some of those more accurate
assertions in review-comments.

## How did you test this change?

- [x] `CIRCLE_NODE_TOTAL=20 CIRCLE_NODE_INDEX=5 yarn test
-r=experimental --env=development --ci`: Can take up to 350s (and use up
to 7GB of memory) on `main` but 11s on this branch
- [x] No more slow `yarn test` parallel runs of `yarn_test` jobs (the
steps in these runs should take <1min but sometimes they take 3min and
end with OOM like
https://app.circleci.com/pipelines/github/facebook/react/38084/workflows/02ca0cbb-bab4-4c19-8d7d-ada814eeebb9/jobs/624258/parallel-runs/5?filterBy=ALL:
Looks good with a sample size of 1
https://app.circleci.com/pipelines/github/facebook/react/38110/workflows/745109a2-b86b-429f-8c01-9b23a245417a/jobs/624651
2023-02-09 10:54:35 +00:00
Mark Erikson 78d2e9e2a8
Replace DevTools `semver` usages with `compare-versions` for smaller bundle size (#26122)
<!--
  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 debug-test --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

This PR:

- Replaces the existing usages of methods from the `semver` library in
the React DevTools source with an inlined version based on
https://www.npmjs.com/package/semver-compare.

This appears to drop the unminified bundle sizes of 3 separate
`react-devtools-extensions` build artifacts by about 50K:


![image](https://user-images.githubusercontent.com/1128784/217326947-4c26d1be-d834-4f77-9e6e-be2d5ed0954d.png)


## How did you test this change?

I was originally working on [a fork of React
DevTools](https://github.com/replayio/react/pull/2) for use with
https://replay.io , specifically our integration of the React DevTools
UI to show the React component tree while users are debugging a recorded
application.

As part of the dev work on that fork, I wanted to shrink the bundle size
of the extension's generated JS build artifacts. I noted that the
official NPM `semver` library was taking up a noticeable chunk of space
in the bundles, and saw that it's only being used in a handful of places
to do some very simple version string comparisons.

I was able to replace the `semver` imports and usages with a simple
alternate comparison function, and confirmed via hands-on checks and
console logging that the checks behaved the same way.

Given that, I wanted to upstream this particular change to help shrink
the real extension's bundle sizes.

I know that it's an extension, so bundle size isn't _as_ critical a
concern as it would be for a pure library. But, smaller download sizes
do benefit all users, and that also includes sites like CodeSandbox and
Replay that are using the React DevTools as a library as well.

I'm happy to tweak this PR if necessary.  Thanks!
2023-02-08 20:00:22 -05:00
Josh Story a3152eda5f
support ReactDOM.render(..., document) without crashing (#26129)
as reported in #26128 `ReactDOM.render(..., document)` crashed when
`enableHostSingletons` was on. This is because it had a different way of
clearing the container than `createRoot(document)`. I updated the legacy
implementation to share the clearing behavior of `creatRoot` which will
preserve the singleton instances.

I also removed the warning saying not to use `document.body` as a
container
2023-02-08 11:32:38 -08:00
Xin Chen 758fc7fde1
Support highlights for React Native apps in dev tools (#26060)
<!--
  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 debug-test --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?
-->

This pull request emit the trace update events `drawTraceUpdates` with
the trace frame information when the trace update drawer runs outside of
web environment. This allows React Devtool running in mobile or other
platforms have a chance to render such highlights and provide similar
feature on web to provide re-render highlights. This is a feature needed
for identifying unnecessary re-renders.

## 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.
-->

I tested this change with Flipper desktop app running against mobile
app, and verified that the event with correct array of frames are
passing through properly.
2023-02-07 14:47:05 -08:00
Sebastian Markbåge 01a0c4e12c
Add Edge Server Builds for workerd / edge-light (#26116)
We currently abuse the browser builds for Web streams derived
environments. We already have a special build for Bun but we should also
have one for [other "edge"
runtimes](https://runtime-keys.proposal.wintercg.org/) so that we can
maximally take advantage of the APIs that exist on each platform.

In practice, we currently check for a global property called
`AsyncLocalStorage` in the server browser builds which we shouldn't
really do since browsers likely won't ever have it. Additionally, this
should probably move to an import which we can't add to actual browser
builds where that will be an invalid import. So it has to be a separate
build. That's not done yet in this PR but Vercel will follow
Cloudflare's lead here.

The `deno` key still points to the browser build since there's no
AsyncLocalStorage there but it could use this same or a custom build if
support is added.
2023-02-07 15:10:01 -05:00
Sebastian Markbåge f0cf832e1d
Update Flight Fixture to "use client" instead of .client.js (#26118)
This updates the Flight fixture to support the new ESM loaders in newer
versions of Node.js.

It also uses native fetch since react-fetch is gone now. (This part
requires Node 18 to run the fixture.)

I also updated everything to use the `"use client"` convention instead
of file name based convention.

The biggest hack here is that the Webpack plugin now just writes every
`.js` file in the manifest. This needs to be more scoped. In practice,
this new convention effectively requires you to traverse the server
graph first to find the actual used files. This is enough to at least
run our own fixture though.

I didn't update the "blocks" fixture.

More details in each commit message.
2023-02-07 12:09:29 -05:00
Sebastian Silbermann 13f4ccfdba
Fix main (#26120)
## Summary

Prettier was bumped recently. So any branch not including that bump,
might bring in outdated formatting (e.g.
https://github.com/facebook/react/pull/26068)

## How did you test this change?

- [x] `yarn prettier-all`
2023-02-07 17:57:43 +01:00
Mengdi Chen c12194f748
[DevTools] improve error handling in extension (#26068)
## Summary

This is to fix some edge cases I recently observed when developing and
using the extension:
- When you reload the page, there's a chance that a port (most likely
the devtools one) is not properly unloaded. In this case, the React
DevTools will stop working unless you create a new tab.
- For unknown reasons, Chrome sometimes spins up two service worker
processes. In this case, an error will be thrown "duplicate ID when
registering content script" and sometimes interrupt the execution of the
rest of service worker.

This is an attempt to make the logic more robust 
- Automatically shutting down the double pipe if the message fails, and
allowing the runtime to rebuild the double pipe.
- Log the error message so Chrome believes we've handled it and will not
interrupt the execution.

This also seems to be helpful in fixing #25806.
2023-02-07 07:59:44 -05:00
Jan Kassens 1445acf777
[CI] cache yarn instead of node_modules (#25834)
The current caching of steps of `node_modules` doesn't work reliable as
is because it includes `arch` in the cache key. `arch` might be
different across workers in the same commit.

I couldn't find a way to optionally restore caches, so what this PR does
is:
- remove the setup step that ran before all other steps and essentially
just populates a circle CI cache key
- all other steps now do: restore yarn cache, `yarn install`, save yarn
cache (fast if already exists)

With this change the initial batch of jobs all race to populate the
cache, but any subsequent jobs should find the existing cache. The
expected downside would be slightly more worker CPU time with all the
parallel jobs, but wall time might be shorter (1 step less in the
critical path) and we should be more reliable as we no longer have the
failure with multiple archs.


## Alternative 1
Remove the `{arch}` from the cache key.

Downside: this might run into weird issues with native dependencies.

## Alternative 2
Somehow check if the cache was restored and only then run a yarn
install.

Downside: couldn't figure out if it's possible to only restore the yarn
cache if restoring the node_modules cache failed. Without that we'd
either always restore both the yarn and node_modules cache or do yarn
installs w/o cache which are prone to failure in the past.
2023-02-06 16:11:17 -05:00
Sebastian Markbåge 03a216070d
Rename "dom" fork to "dom-node" and "bun" fork to "dom-bun" (#26117)
The "dom" configuration is actually the node specific configuration. It
just happened to be that this was the mainline variant before so it was
implied but with so many variants, this is less obvious now.

The "bun" configuration is specifically for "bun". There's no "native"
renderer for "bun" yet.
2023-02-06 15:54:14 -05:00
Sebastian Markbåge 4bf2113a15
Revert "Move the Webpack manifest config to one level deeper (#26083)" (#26111)
Just kidding. We're not going to need any other fields afaik after all.
2023-02-06 10:50:52 -05:00
Andrew Clark 855b77c9bb
publish-prereleases: Exit if CircleCI request fails (#26100)
If the publish-prereleases command fails to access CircleCI, it will now
exit with a message instead of hanging indefinitely.
2023-02-02 19:20:34 -05:00
Jan Kassens 2ef24145e4
[flow] upgrade to 0.199.0 (#26096)
`flow-remove-types` was also upgraded to the latest version.
2023-02-02 16:19:05 -05:00
Sebastian Markbåge 922dd7ba50
Revert the outer module object to an object (#26093)
This is because Webpack has a `typeof ... === 'object'` before its esm
compat test.

This is unfortunate because it means we can't have a nice error in CJS
when someone does this:

```
const fn = require('client-fn');
fn();
```

I also fixed some checks in the validator that read off the client ref.
It shouldn't do those checks against a client ref, since those now
throw.
2023-02-02 15:30:59 -05:00
Sebastian Markbåge 9d111ffdfb
Serialize Promises through Flight (#26086)
This lets you pass Promises from server components to client components
and `use()` them there.

We still don't support Promises as children on the client, so we need to
support both. This will be a lot simpler when we remove the need to
encode children as lazy since we don't need the lazy encoding anymore
then.

I noticed that this test failed because we don't synchronously resolve
instrumented Promises if they're lazy. The second fix calls `.then()`
early to ensure that this lazy initialization can happen eagerly. ~It
felt silly to do this with an empty function or something, so I just did
the attachment of ping listeners early here. It's also a little silly
since they will ping the currently running render for no reason if it's
synchronously available.~ EDIT: That didn't work because a ping might
interrupt the current render. Probably need a bigger refactor.

We could add another extension but we've already taken a lot of
liberties with the Promise protocol. At least this is one that doesn't
need extension of the protocol as much. Any sub-class of promises could
do this.
2023-02-01 12:56:53 -05:00
Ming Ye 0ba4698c7b
Fix async test in React reconciler (#26087) 2023-02-01 09:59:41 +01:00
Sebastian Markbåge 8c234c0de9
Move the Webpack manifest config to one level deeper (#26083)
This frees up the Webpack manifest to contain a `serverManifest` part
too.

@shuding
2023-01-31 23:33:31 -05:00
Sebastian Markbåge 977bccd24d
Refactor Flight Encoding (#26082)
This is just shifting around some encoding strategies for Flight in
preparation for more types.

```
S1:"react.suspense"
J2:["$", "$1", {children: "@3"}]
J3:"Hello"
```

```
1:"$Sreact.suspense"
2:["$", "$1", {children: "$L3"}]
3:"Hello"
```
2023-01-31 12:41:36 -05:00
Ming Ye 8b9ac8175f
Remove unused dependency 'abort-controller' (#26074)
## Summary
This PR removes the unused dependency 'abort-controller' from the
project. it helps to keep the project clean and maintainable.

## How did you test this change?
ci green
2023-01-31 10:47:14 -05:00
Ming Ye d7bb524ade
[cleanup] Remove unused package jest-mock-scheduler (#26084)
## Summary

Removing package jest-mock-scheduler introduced in PR
https://github.com/facebook/react/pull/14358, as it is no longer
referenced in the main branch code. The following files previously
referenced it:

- packages/scheduler/src/__tests__/Scheduler-test.js
- packages/scheduler/src/__tests__/SchedulerDOM-test.js
- packages/shared/__tests__/ReactDOMFrameScheduling-test.js
- scripts/jest/setupTests.js
- scripts/rollup/bundles.js

## How did you test this change?

ci green
2023-01-31 10:23:31 -05:00
Jan Kassens 6b30832666
Upgrade prettier (#26081)
The old version of prettier we were using didn't support the Flow syntax
to access properties in a type using `SomeType['prop']`. This updates
`prettier` and `rollup-plugin-prettier` to the latest versions.

I added the prettier config `arrowParens: "avoid"` to reduce the diff
size as the default has changed in Prettier 2.0. The largest amount of
changes comes from function expressions now having a space. This doesn't
have an option to preserve the old behavior, so we have to update this.
2023-01-31 08:25:05 -05:00
Jan Kassens 1f5ce59dd7
[cleanup] fully roll out warnAboutSpreadingKeyToJSX (#26080)
I fully enabled this flag internally now and unless I see complications,
we should be able to clean this up in the code.
2023-01-30 15:25:24 -05:00
an onion 48b687fc95
[trusted types][www] Add enableTrustedTypesIntegration flag back in (#26016)
## Summary

The flag was first added in #16157 and was rolled out to employees in
D17430095. #25997 removed this flag because it wasn't dynamically set to
a value in www. The www side was mistakenly removed in D41851685 due to
deprecation of a TypedJSModule but we still want to keep this flag, so
let's add it back in + add a GK on the www side to match the previous
rollout.

See D42574435 for the dynamic value change in www

## How did you test this change?

```
yarn test
yarn test --prod
```
2023-01-30 13:26:04 -05:00
Samuel Susla 9b1423cc09
Revert "Hold host functions in var" (#26079)
Revert https://github.com/facebook/react/commit/353c30252. The commit
breaks old React Native where `nativeFabricUIManager` is undefined. I
need to add unit test for this to make sure it doesn't happen in the
future and create a mechanism to deal with undefined
`nativeFabricUIManager`.
This is to unblock React sync to React Native.
2023-01-30 17:23:02 +00:00
Sebastian Silbermann b0671f9ea0
Include removal of scheduler/tracing in changelog (#26063) 2023-01-30 08:12:48 +01:00
Sebastian Markbåge ce09ace9a2
Improve Error Messages when Access Client References (#26059)
This renames Module References to Client References, since they are in
the server->client direction.

I also changed the Proxies exposed from the `node-register` loader to
provide better error messages. Ideally, some of this should be
replicated in the ESM loader too but neither are the source of truth.
We'll replicate this in the static form in the Next.js loaders. cc
@huozhi @shuding

- All references are now functions so that when you call them on the
server, we can yield a better error message.
- References that are themselves already referring to an export name are
now proxies that error when you dot into them.
- `use(...)` can now be used on a client reference to unwrap it server
side and then pass a reference to the awaited value.
2023-01-27 20:08:26 -05:00
Mengdi Chen 78c4bec207
[DevTools] fix local build for extension (#26067)
## Summary

resolves #26051

After we upgrade to Manifest V3, the browser no longer allow us to run
`eval` within the extension. It's not a problem for prod build, but for
dev build, webpack has been using eval to inject the source map for
devtool. This PR changes it to an alternative method.
2023-01-27 15:35:07 -05:00
Jan Kassens cb16201180
Update danger.js token (#26066)
The old token was revoked, this updates the token by reading from CI
secrets instead, I'm not sure there's benefit in making it publicly
visible.
2023-01-27 14:05:08 -05:00
Samuel Susla 0652bdbd10
Add flow types to Maps in ReactNativeViewConfigRegistry.js (#26064)
Need to add types to these two maps to unblock React Native sync.
2023-01-27 16:55:38 +00:00
Jan Kassens ee85098019
[cleanup] remove deletedTreeCleanUpLevel feature flag (#25529)
I noticed this was an experiment concluded 16 months ago (#21679) that
this extra work is beneficial
to break up cycles leaking memory in product code.
2023-01-17 11:03:29 -05:00
Sebastian Silbermann 4f8ffec453
Rejct toWarnDev if given callback throws (#26003)
## Summary

Should unblock https://github.com/facebook/react/pull/25970
If the callback for `toWarnDev` was `async` and threw, we didn't
ultimately reject the await Promise from the matcher. This resulted in
tests failing even though the failure was expected due to a test gate.

## How did you test this change?

- [x] tested in https://github.com/facebook/react/pull/25970 with `yarn
test --r=stable --env=development
packages/react-dom/src/__tests__/ReactDOMFizzServer-test.js --watch`
- [x] `yarn test`
- [x] CI
2023-01-15 18:57:59 +01:00
Jan Kassens 0e31dd028e
Remove findDOMNode www shim (#25998)
This shim is no longer needed on www, in fact I had already deleted it
there and it's currently not on www. See D42503692 which is trying to
add it back as I didn't realize this file was synced from GitHub.
2023-01-13 16:27:03 -05:00
Jan Kassens 379dd741e9
[www] set enableTrustedTypesIntegration to false (#25997)
This isn't configured to a dynamic value on www, so hardcode here to
false.
2023-01-13 16:02:24 -05:00
Andrey Lunyov 489d00fa61
[cleanup] Remove warnAboutDeprecatedLifecycles feature flag (#25992)
This `warnAboutDeprecatedLifecycles` is always true, and should be safe
to remove.
2023-01-12 16:57:14 -05:00
Sebastian Silbermann 555ece0cd1
Don't warn about concurrently rendering contexts if we finished rendering (#22797)
Closes https://github.com/facebook/react/issues/22796
2023-01-12 13:17:15 +01:00
Jan Kassens 0fce6bb498
[cleanup] remove feature flags warnAboutDefaultPropsOnFunctionComponents and warnAboutStringRefs (#25980)
These feature flags are fully rolled out and easy to clean up. Let's
remove them!
2023-01-11 12:19:46 -05:00
Jan Kassens 7002a6743e
[cleanup] remove unused values from ReactFeatureFlags.www-dynamic (#25575)
These values are never imported into `ReactFeatureFlags.www.js`, so
they're unused:
- `allowConcurrentByDefault`
- `consoleManagedByDevToolsDuringStrictMode`

These values are never set in the WWW module
(https://fburl.com/code/dsb2ohv8), so they're always `undefined` on www:
- `createRootStrictEffectsByDefault`
- `enableClientRenderFallbackOnTextMismatch`
2023-01-10 23:26:01 -05:00
Tianyu Yao fb324faf8a
Test case for stack overflow in ReactFizzServer (#25971)
SSR currently stack overflows when the component tree is extremely large
2023-01-10 16:53:16 -08:00
Jan Kassens a48e54f2b7
[cleanup] remove old feature flag warnAboutDeprecatedLifecycles (#25978)
This feature flag was always set to true, we can easily clean it up.
2023-01-10 15:30:42 -05:00
Jan Kassens 0f4a835966
Remove duplicate JSResourceReferenceImpl mock (#25976)
This mock exists in 2 directories (with identical implementation) and
Jest just picks one at random. This removes one which makes it at least
deterministic and fixes a Jest warning on startup.

It existed in these 2 places:
-
`packages/react-server-dom-relay/src/__mocks__/JSResourceReferenceImpl.js`
-
`packages/react-server-native-relay/src/__mocks__/JSResourceReferenceImpl.js`
(removed)
2023-01-10 10:32:59 -05:00
Jan Kassens c49131669b
Remove unused Flow suppressions (#25977)
These suppressions are no longer required.

Generated using:
```sh
flow/tool update-suppressions .
```
followed by adding back 1 or 2 suppressions that were only triggered in
some configurations.
2023-01-10 10:32:42 -05:00
Chris afe6521e13
Refactor: remove useless parameter (#25923)
## Summary

I was reading the source code of `ReactFiberLane.js` and I found the
third parameter of the function markRootPinged was not used. So I think
we can remove it.

## How did you test this change?

There is no logic changed, so I think there is no need to add unit
tests. So I run `yarn test` and `yarn test --prod` locally and all tests
are passed.

Co-authored-by: Jan Kassens <jkassens@meta.com>
2023-01-09 23:25:02 -05:00
Hoikan 1253462ea4
Refactor: Reuse variable "remoteRepoDir" (#25740)
Reuse variable `remoteRepoDir` , same with `join(__dirname, 'remote-repo')`.
2023-01-09 22:59:38 -05:00
Jan Kassens 34464fb16c
Upgrade to Flow 0.196.3 (#25974)
After the previous changes these upgrade are easy.

- removes config options that were removed
- object index access now requires an indexer key in the type, this
cause a handful of errors that were fixed
- undefined keys error in all places, this needed a few extra
suppressions for repeated undefined identifiers.

Flow's
[CHANGELOG.md](https://github.com/facebook/flow/blob/main/Changelog.md).
2023-01-09 17:52:42 -05:00
Jan Kassens e2424f33b3
[flow] enable exact_empty_objects (#25973)
This enables the "exact_empty_objects" setting for Flow which makes
empty objects exact instead of building up the type as properties are
added in code below. This is in preparation to Flow 191 which makes this
the default and removes the config.

More about the change in the Flow blog
[here](https://medium.com/flow-type/improved-handling-of-the-empty-object-in-flow-ead91887e40c).
2023-01-09 17:00:36 -05:00
Jan Kassens 0b4f443020
[flow] enable enforce_local_inference_annotations (#25921)
This setting is an incremental path to the next Flow version enforcing
type annotations on most functions (except some inline callbacks).

Used
```
node_modules/.bin/flow codemod annotate-functions-and-classes --write .
```
to add a majority of the types with some hand cleanup when for large
inferred objects that should just be `Fiber` or weird constructs
including `any`.

Suppressed the remaining issues.

Builds on #25918
2023-01-09 15:46:48 -05:00
mofeiZ 0b974418c9
[Fizz] Fork Fizz instruction set for inline script and external runtime (#25862)
~~[Fizz] Duplicate completeBoundaryWithStyles to not reference globals~~

## Summary

Follow-up / cleanup PR to #25437 

- `completeBoundaryWithStylesInlineLocals` is used by the Fizz external
runtime, which bundles together all Fizz instruction functions (and is
able to reference / rename `completeBoundary` and `resourceMap` as
locals).
- `completeBoundaryWithStylesInlineGlobals` is used by the Fizz inline
script writer, which sends Fizz instruction functions on an as-needed
basis. This version needs to reference `completeBoundary($RC)` and
`resourceMap($RM)` as globals.

Ideally, Closure would take care of inlining a shared implementation,
but I couldn't figure out a zero-overhead inline due to lack of an
`@inline` compiler directive. It seems that Closure thinks that a shared
`completeBoundaryWithStyles` is too large and will always keep it as a
separate function. I've also tried currying / writing a higher order
function (`getCompleteBoundaryWithStyles`) with no luck



## How did you test this change?
- generated Fizz inline instructions should be unchanged
- bundle size for unstable_external_runtime should be slightly smaller
(due to lack of globals)
- `ReactDOMFizzServer-test.js` and `ReactDOMFloat-test.js` should be
unaffected
2023-01-06 14:28:55 -05:00
Tianyu Yao 5379b6123f
Batch sync, default and continuous lanes (#25700)
<!--
  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 debug-test --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?
-->
This is the other approach for unifying default and sync lane
https://github.com/facebook/react/pull/25524.
The approach in that PR is to merge default and continuous lane into the
sync lane, and use a new field to track the priority. But there are a
couple places that field will be needed, and it is difficult to
correctly reset the field when there is no sync lane.

In this PR we take the other approach that doesn't remove any lane, but
batch them to get the behavior we want.


## 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.
-->
yarn test

Co-authored-by: Andrew Clark <hi@andrewclark.io>
2023-01-05 15:21:35 -08:00
Ming Ye bbf4d22113
Update import for babel-code-frame in build script (#25963)
## Summary

Updating import for babel-code-frame to use the official @babel package,
as babel-code-frame is a ghost dependency. This change is necessary to
avoid potential issues and stay up-to-date with the latest version of
@babel/code-frame, which is already declared in our project's
package.json.

## How did you test this change?
yarn test
2023-01-05 15:56:31 -05:00
Jan Kassens b83baf63f7
Transform updates to support Flow this annotation syntax (#25918)
Flow introduced a new syntax to annotated the context type of a
function, this tries to update the rest and add 1 example usage.

- 2b1fb91a55 already added the changes
required for eslint.
- Jest transform is updated to use the recommended `hermes-parser` which
can parse current and Flow syntax and will be updated in the future.
- Rollup uses a new plugin to strip the flow types. This isn't ideal as
the npm module is deprecated in favor of using `hermes-parser`, but I
couldn't figure out how to integrate that with Rollup.
2023-01-05 15:41:49 -05:00
Mengdi Chen 2619886ac0
fix function type for flow (#25965)
These files fail CI `yarn_flow`.
2023-01-05 15:27:51 -05:00
Mengdi Chen ff9f943741
[DevTools] add perf regression test page in shell (#25078)
## Summary

This PR adds a "perf regression tests" page to react-devtools-shell.
This page is meant to be used as a performance sanity check we will run
whenever we release a new version or finish a major refactor.
Similar to other pages in the shell, this page can load the inline
version of devtools and a test react app on the same page. But this page
does not load devtools automatically like other pages. Instead, it
provides a button that allows us to load devtools on-demand, so that we
can easily compare perf numbers without devtools against the numbers
with devtools.

<img width="561" alt="image"
src="https://user-images.githubusercontent.com/1001890/184059633-e4f0852c-8464-4d94-8064-1684eee626f4.png">

As a first step, this page currently only contain one test:
mount/unmount a large subtree. This is to catch perf issues that
devtools can cause on the react applications it's running on, which was
once a bug fixed in #24863.
In the future, we plan to add:
- more test apps covering different scenarios 
- perf numbers within devtools (e.g. initial load) 

## How did you test this change?

In order to show this test app can actually catch the perf regression
it's aiming at, I reverted #24863 locally. Here is the result:


https://user-images.githubusercontent.com/1001890/184059214-9c9b308c-173b-4dd7-b815-46fbd7067073.mov

As shown in the video, the time it takes to unmount the large subtree
significantly increased after DevTools is loaded.

For comparison, here is how it looks like before the fix was reverted:
<img width="452" alt="image"
src="https://user-images.githubusercontent.com/1001890/184059743-0968bc7d-4ce4-42cd-b04a-f6cbc078d4f4.png">

## about the `requestAnimationFrame` method

For this test, I used `requestAnimationFrame` to catch the time when
render and commit are done. It aligns very well with the numbers
reported by Chrome DevTools performance profiling. For example, in one
run, the numbers reported by my method are
<img width="464" alt="image"
src="https://user-images.githubusercontent.com/1001890/184060228-990a4c75-f594-411a-9f85-fa5532ec8c37.png">
They are very close to the numbers reported by Chrome profiling:
<img width="456" alt="image"
src="https://user-images.githubusercontent.com/1001890/184060355-a15d1ec5-c296-4016-9c83-03e761f387e3.png">

<img width="354" alt="image"
src="https://user-images.githubusercontent.com/1001890/184060375-19029010-3aed-4a23-890e-397cdba86d9e.png">

`<Profiler>` is not able to catch this issue here.

If you are aware of a better way to do this, please kindly share with
me.
2023-01-04 17:31:13 -05:00
Andrew Clark c2d6552079
Unify `use` and `renderDidSuspendDelayIfPossible` implementations (#25922)
When unwrapping a promise with `use`, we sometimes suspend the work loop
from rendering anything else until the data has resolved. This is
different from how Suspense works in the old throw-a-promise world,
where rather than suspend rendering midway through the render phase, we
prepare a fallback and block the commit at the end, if necessary;
however, the logic for determining whether it's OK to block is the same.
The implementation is only incidentally different because it happens in
two different parts of the code. This means for `use`, we end up doing
the same checks twice, which is wasteful in terms of computation, but
also introduces a risk that the logic will accidentally diverge.

This unifies the implementation by moving it into the SuspenseContext
module. Most of the logic for deciding whether to suspend is already
performed in the begin phase of SuspenseComponent, so it makes sense to
store that information on the stack rather than recompute it on demand.

The way I've chosen to model this is to track whether the work loop is
rendering inside the "shell" of the tree. The shell is defined as the
part of the tree that's visible in the current UI. Once we enter a new
Suspense boundary (or a hidden Offscreen boundary, which acts a Suspense
boundary), we're no longer in the shell. This is already how Suspense
behavior was modeled in terms of UX, so using this concept directly in
the implementation turns out to result in less code than before.

For the most part, this is purely an internal refactor, though it does
fix a bug in the `use` implementation related to nested Suspense
boundaries. I wouldn't be surprised if it happens to fix other bugs that
we haven't yet discovered, especially around Offscreen. I'll add more
tests as I think of them.
2023-01-04 15:11:56 -05:00
Andrew Clark 48274a43aa
Remove vestigial Suspense batching logic (#25861)
This code was originally added in the old ExpirationTime implementation
of Suspense. The idea is that if multiple updates suspend inside the
same Suspense boundary, and both of them resolve, we should render both
results in the same batch, to reduce jank.

This was an incomplete idea, though. We later discovered a stronger
requirement — once we show a fallback, we cannot fill in that fallback
without completing _all_ the updates that were previously skipped over.
Otherwise you get tearing. This was fixed by #18411, then we discovered
additional related flaws that were addressed in #24685. See those PR
descriptions for additional context.

So I believe this older code is no longer necessary.
2023-01-04 14:50:00 -05:00
Steven de7d1c9071
Add `fetchPriority` to `<img>` and `<link>` (#25927)
<!--
  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 debug-test --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

- Fixes https://github.com/facebook/react/issues/25682

## How did you test this change?

I tried this but it didn't work
```
yarn build --type=UMD_DEV react/index,react-dom && cd fixtures/attribute-behavior && yarn install && yarn start
```

Co-authored-by: eps1lon <silbermann.sebastian@gmail.com>
2022-12-23 14:31:27 -05:00
satelllte 81d4ee9ca5
reconciler docs: fix small typo - "mode" (instead of "node") (#25863) 2022-12-23 13:22:55 +01:00
KZ-Lucas 726a40eded
CHANGELOG.md Change parentheses position (#25762) 2022-12-23 12:43:06 +01:00
Andrew Clark 5fcf1a4b4c
Bugfix: Synchronous ping during render phase sometimes unwinds the stack, leading to crash (#25851)
I found this bug when working on a different task.

`pingSuspendedRoot` sometimes calls `prepareFreshStack` to interupt the
work-in-progress tree and force a restart from the root. The idea is
that if the current render is already in a state where it be blocked
from committing, and there's new data that could unblock it, we might as
well restart from the beginning.

The problem is that this is only safe to do if `pingSuspendedRoot` is
called from a non-React task, like an event handler or a microtask.
While this is usually the case, it's entirely possible for a thenable to
resolve (i.e. to call `pingSuspendedRoot`) synchronously while the
render phase is already executing. If that happens, and work loop
attempts to unwind the stack, it causes the render phase to crash.
2022-12-21 23:55:49 -05:00
Jan Kassens 2b1fb91a55
ESLint upgrade to use hermes-eslint (#25915)
Hermes parser is the preferred parser for Flow code going forward. We
need to upgrade to this parser to support new Flow syntax like function
`this` context type annotations or `ObjectType['prop']` syntax.

Unfortunately, there's quite a few upgrades here to make it work somehow
(dependencies between the changes)

- ~Upgrade `eslint` to `8.*`~ reverted this as the React eslint plugin
tests depend on the older version and there's a [yarn
bug](https://github.com/yarnpkg/yarn/issues/6285) that prevents
`devDependencies` and `peerDependencies` to different versions.
- Remove `eslint-config-fbjs` preset dependency and inline the rules,
imho this makes it a lot clearer what the rules are.
- Remove the turned off `jsx-a11y/*` rules and it's dependency instead
of inlining those from the `fbjs` config.
- Update parser and dependency from `babel-eslint` to `hermes-eslint`.
- `ft-flow/no-unused-expressions` rule replaces `no-unused-expressions`
which now allows standalone type asserts, e.g. `(foo: number);`
- Bunch of globals added to the eslint config
- Disabled `no-redeclare`, seems like the eslint upgrade started making
this more precise and warn against re-defined globals like
`__EXPERIMENTAL__` (in rollup scripts) or `fetch` (when importing fetch
from node-fetch).
- Minor lint fixes like duplicate keys in objects.
2022-12-20 14:27:01 -05:00
1192 changed files with 68398 additions and 68493 deletions

View File

@ -7,40 +7,11 @@ aliases:
- &environment
TZ: /usr/share/zoneinfo/America/Los_Angeles
- &restore_yarn_cache
restore_cache:
name: Restore yarn cache
keys:
- v1-yarn_cache-{{ arch }}-{{ checksum "yarn.lock" }}
- v1-yarn_cache-{{ arch }}-
- v1-yarn_cache-
- &yarn_install
run:
name: Install dependencies
command: yarn install --frozen-lockfile --cache-folder ~/.cache/yarn
- &yarn_install_retry
run:
name: Install dependencies (retry)
when: on_fail
command: yarn install --frozen-lockfile --cache-folder ~/.cache/yarn
- &save_yarn_cache
save_cache:
name: Save yarn cache
key: v1-yarn_cache-{{ arch }}-{{ checksum "yarn.lock" }}
paths:
- ~/.cache/yarn
- &restore_yarn_cache_fixtures_dom
restore_cache:
name: Restore yarn cache for fixtures/dom
keys:
- v1-yarn_cache-{{ arch }}-{{ checksum "yarn.lock" }}-fixtures/dom
- v1-yarn_cache-{{ arch }}-{{ checksum "yarn.lock" }}
- v1-yarn_cache-{{ arch }}-
- v1-yarn_cache-
- v2-yarn_cache-{{ arch }}-{{ checksum "yarn.lock" }}-fixtures/dom
- &yarn_install_fixtures_dom
run:
@ -58,51 +29,36 @@ aliases:
- &save_yarn_cache_fixtures_dom
save_cache:
name: Save yarn cache for fixtures/dom
key: v1-yarn_cache-{{ arch }}-{{ checksum "yarn.lock" }}-fixtures/dom
key: v2-yarn_cache-{{ arch }}-{{ checksum "yarn.lock" }}-fixtures/dom
paths:
- ~/.cache/yarn
- &save_node_modules
save_cache:
name: Save node_modules cache
# Cache only for the current revision to prevent cache injections from
# malicious PRs.
key: v1-node_modules-{{ arch }}-{{ .Revision }}
paths:
- node_modules
- packages/eslint-plugin-react-hooks/node_modules
- packages/react-art/node_modules
- packages/react-client/node_modules
- packages/react-devtools-core/node_modules
- packages/react-devtools-extensions/node_modules
- packages/react-devtools-inline/node_modules
- packages/react-devtools-shared/node_modules
- packages/react-devtools-shell/node_modules
- packages/react-devtools-timeline/node_modules
- packages/react-devtools/node_modules
- packages/react-dom/node_modules
- packages/react-interactions/node_modules
- packages/react-native-renderer/node_modules
- packages/react-reconciler/node_modules
- packages/react-server-dom-relay/node_modules
- packages/react-server-dom-webpack/node_modules
- packages/react-server-native-relay/node_modules
- packages/react-server/node_modules
- packages/react-test-renderer/node_modules
- packages/react/node_modules
- packages/scheduler/node_modules
- &restore_node_modules
restore_cache:
name: Restore node_modules cache
keys:
- v1-node_modules-{{ arch }}-{{ .Revision }}
- &TEST_PARALLELISM 20
- &attach_workspace
at: build
commands:
setup_node_modules:
description: "Restore node_modules"
steps:
- restore_cache:
name: Restore yarn cache
keys:
- v2-yarn_cache-{{ arch }}-{{ checksum "yarn.lock" }}
- run:
name: Install dependencies
command: |
yarn install --frozen-lockfile --cache-folder ~/.cache/yarn
if [ $? -ne 0 ]; then
yarn install --frozen-lockfile --cache-folder ~/.cache/yarn
fi
- save_cache:
name: Save yarn cache
key: v2-yarn_cache-{{ arch }}-{{ checksum "yarn.lock" }}
paths:
- ~/.cache/yarn
# The CircleCI API doesn't yet support triggering a specific workflow, but it
# does support triggering a pipeline. So as a workaround you can triggger the
# entire pipeline and use parameters to disable everything except the workflow
@ -115,28 +71,13 @@ parameters:
default: ''
jobs:
setup:
docker: *docker
environment: *environment
steps:
- checkout
- run:
name: NodeJS Version
command: node --version
- *restore_yarn_cache
- *restore_node_modules
- *yarn_install
- *yarn_install_retry
- *save_yarn_cache
- *save_node_modules
yarn_lint:
docker: *docker
environment: *environment
steps:
- checkout
- *restore_node_modules
- setup_node_modules
- run: node ./scripts/prettier/index
- run: node ./scripts/tasks/eslint
- run: ./scripts/circleci/check_license.sh
@ -150,7 +91,7 @@ jobs:
steps:
- checkout
- *restore_node_modules
- setup_node_modules
- run: node ./scripts/tasks/flow-ci
scrape_warning_messages:
@ -159,7 +100,7 @@ jobs:
steps:
- checkout
- *restore_node_modules
- setup_node_modules
- run:
command: |
mkdir -p ./build
@ -169,14 +110,14 @@ jobs:
paths:
- build
yarn_build_combined:
yarn_build:
docker: *docker
environment: *environment
parallelism: 40
steps:
- checkout
- *restore_node_modules
- run: yarn build-combined
- setup_node_modules
- run: yarn build
- persist_to_workspace:
root: .
paths:
@ -190,7 +131,7 @@ jobs:
type: string
steps:
- checkout
- *restore_node_modules
- setup_node_modules
- run:
name: Download artifacts for revision
command: |
@ -207,14 +148,36 @@ jobs:
environment: *environment
steps:
- checkout
- *restore_node_modules
- setup_node_modules
- run:
name: Download artifacts for base revision
# TODO: The download-experimental-build.js script works by fetching
# artifacts from CI. CircleCI recently updated this endpoint to
# require an auth token. This is a problem for PR branches, where
# sizebot needs to run, because we don't want to leak the token to
# arbitrary code written by an outside contributor.
#
# This only affects PR branches. CI workflows that run on the main
# branch are allowed to access environment variables, because only those
# with push access can land code in main.
#
# As a temporary workaround, we'll fetch the assets from a mirror.
# Need to figure out a longer term solution for this.
#
# Original code
#
# command: |
# git fetch origin main
# cd ./scripts/release && yarn && cd ../../
# scripts/release/download-experimental-build.js --commit=$(git merge-base HEAD origin/main) --allowBrokenCI
# mv ./build ./base-build
#
# Workaround. Fetch the artifacts from react-builds.vercel.app. This
# is the same app that hosts the sizebot diff previews.
command: |
git fetch origin main
cd ./scripts/release && yarn && cd ../../
scripts/release/download-experimental-build.js --commit=$(git merge-base HEAD origin/main) --allowBrokenCI
curl -L --retry 60 --retry-delay 10 --retry-max-time 600 https://react-builds.vercel.app/api/commits/$(git merge-base HEAD origin/main)/artifacts/build.tgz | tar -xz
mv ./build ./base-build
- run:
# TODO: The `download-experimental-build` script copies the npm
# packages into the `node_modules` directory. This is a historical
@ -235,7 +198,7 @@ jobs:
- checkout
- attach_workspace:
at: .
- *restore_node_modules
- setup_node_modules
- run: echo "<< pipeline.git.revision >>" >> build/COMMIT_SHA
# Compress build directory into a single tarball for easy download
- run: tar -zcvf ./build.tgz ./build
@ -254,7 +217,7 @@ jobs:
- attach_workspace:
at: .
- run: echo "<< pipeline.git.revision >>" >> build/COMMIT_SHA
- *restore_node_modules
- setup_node_modules
- run:
command: node ./scripts/tasks/danger
@ -265,7 +228,7 @@ jobs:
- checkout
- attach_workspace:
at: .
- *restore_node_modules
- setup_node_modules
- run:
environment:
RELEASE_CHANNEL: experimental
@ -280,7 +243,7 @@ jobs:
- checkout
- attach_workspace:
at: .
- *restore_node_modules
- setup_node_modules
- run:
name: Playwright install deps
command: |
@ -302,7 +265,7 @@ jobs:
- checkout
- attach_workspace:
at: .
- *restore_node_modules
- setup_node_modules
- run: ./scripts/circleci/download_devtools_regression_build.js << parameters.version >> --replaceBuild
- run: node ./scripts/jest/jest-cli.js --build --project devtools --release-channel=experimental --reactVersion << parameters.version >> --ci
@ -317,7 +280,7 @@ jobs:
- checkout
- attach_workspace:
at: .
- *restore_node_modules
- setup_node_modules
- run:
name: Playwright install deps
command: |
@ -341,7 +304,7 @@ jobs:
- checkout
- attach_workspace:
at: .
- *restore_node_modules
- setup_node_modules
- run: yarn lint-build
yarn_check_release_dependencies:
@ -351,7 +314,7 @@ jobs:
- checkout
- attach_workspace:
at: .
- *restore_node_modules
- setup_node_modules
- run: yarn check-release-dependencies
@ -361,7 +324,7 @@ jobs:
steps:
- checkout
- attach_workspace: *attach_workspace
- *restore_node_modules
- setup_node_modules
- run:
name: Search build artifacts for unminified errors
command: |
@ -374,7 +337,7 @@ jobs:
steps:
- checkout
- attach_workspace: *attach_workspace
- *restore_node_modules
- setup_node_modules
- run:
name: Confirm generated inline Fizz runtime is up to date
command: |
@ -390,7 +353,7 @@ jobs:
type: string
steps:
- checkout
- *restore_node_modules
- setup_node_modules
- run: yarn test <<parameters.args>> --ci
yarn_test_build:
@ -404,7 +367,7 @@ jobs:
- checkout
- attach_workspace:
at: .
- *restore_node_modules
- setup_node_modules
- run: yarn test --build <<parameters.args>> --ci
RELEASE_CHANNEL_stable_yarn_test_dom_fixtures:
@ -414,7 +377,7 @@ jobs:
- checkout
- attach_workspace:
at: .
- *restore_node_modules
- setup_node_modules
- *restore_yarn_cache_fixtures_dom
- *yarn_install_fixtures_dom
- *yarn_install_fixtures_dom_retry
@ -425,7 +388,7 @@ jobs:
RELEASE_CHANNEL: stable
working_directory: fixtures/dom
command: |
yarn prestart
yarn predev
yarn test --maxWorkers=2
test_fuzz:
@ -433,7 +396,7 @@ jobs:
environment: *environment
steps:
- checkout
- *restore_node_modules
- setup_node_modules
- run:
name: Run fuzz tests
command: |
@ -452,7 +415,7 @@ jobs:
environment: *environment
steps:
- checkout
- *restore_node_modules
- setup_node_modules
- run:
name: Run publish script
command: |
@ -463,29 +426,30 @@ jobs:
scripts/release/publish.js --ci --tags << parameters.dist_tag >>
workflows:
version: 2
# New workflow that will replace "stable" and "experimental"
build_and_test:
unless: << pipeline.parameters.prerelease_commit_sha >>
jobs:
- setup:
- yarn_flow:
filters:
branches:
ignore:
- builds/facebook-www
- yarn_flow:
requires:
- setup
- check_generated_fizz_runtime:
requires:
- setup
filters:
branches:
ignore:
- builds/facebook-www
- yarn_lint:
requires:
- setup
filters:
branches:
ignore:
- builds/facebook-www
- yarn_test:
requires:
- setup
filters:
branches:
ignore:
- builds/facebook-www
matrix:
parameters:
args:
@ -508,19 +472,23 @@ workflows:
# TODO: Test more persistent configurations?
- '-r=stable --env=development --persistent'
- '-r=experimental --env=development --persistent'
- yarn_build_combined:
requires:
- setup
- yarn_build:
filters:
branches:
ignore:
- builds/facebook-www
- scrape_warning_messages:
requires:
- setup
filters:
branches:
ignore:
- builds/facebook-www
- process_artifacts_combined:
requires:
- scrape_warning_messages
- yarn_build_combined
- yarn_build
- yarn_test_build:
requires:
- yarn_build_combined
- yarn_build
matrix:
parameters:
args:
@ -551,8 +519,7 @@ workflows:
branches:
ignore:
- main
requires:
- setup
- builds/facebook-www
- sizebot:
filters:
branches:
@ -560,22 +527,22 @@ workflows:
- main
requires:
- download_base_build_for_sizebot
- yarn_build_combined
- yarn_build
- yarn_lint_build:
requires:
- yarn_build_combined
- yarn_build
- yarn_check_release_dependencies:
requires:
- yarn_build_combined
- yarn_build
- check_error_codes:
requires:
- yarn_build_combined
- yarn_build
- RELEASE_CHANNEL_stable_yarn_test_dom_fixtures:
requires:
- yarn_build_combined
- yarn_build
- build_devtools_and_process_artifacts:
requires:
- yarn_build_combined
- yarn_build
- run_devtools_e2e_tests:
requires:
- build_devtools_and_process_artifacts
@ -591,10 +558,7 @@ workflows:
only:
- main
jobs:
- setup
- test_fuzz:
requires:
- setup
- test_fuzz
devtools_regression_tests:
unless: << pipeline.parameters.prerelease_commit_sha >>
@ -607,10 +571,7 @@ workflows:
only:
- main
jobs:
- setup
- download_build:
requires:
- setup
revision: << pipeline.git.revision >>
- build_devtools_and_process_artifacts:
requires:
@ -642,14 +603,21 @@ workflows:
publish_preleases:
when: << pipeline.parameters.prerelease_commit_sha >>
jobs:
- setup
- publish_prerelease:
name: Publish to Next channel
requires:
- setup
name: Publish to Canary channel
commit_sha: << pipeline.parameters.prerelease_commit_sha >>
release_channel: stable
dist_tag: "next"
# The tags to use when publishing canaries. The main one we should
# always include is "canary" but we can use multiple (e.g. alpha,
# beta, rc). To declare multiple, use a comma-separated string, like
# this:
# dist_tag: "canary,alpha,beta,rc"
#
# TODO: We currently tag canaries with "next" in addition to "canary"
# because this used to be called the "next" channel and some
# downstream consumers might still expect that tag. We can remove this
# after some time has elapsed and the change has been communicated.
dist_tag: "canary,next"
- publish_prerelease:
name: Publish to Experimental channel
requires:
@ -657,7 +625,7 @@ workflows:
# will sometimes fail if you try to concurrently publish two
# different versions of the same package, even if they use different
# dist tags.
- Publish to Next channel
- Publish to Canary channel
commit_sha: << pipeline.parameters.prerelease_commit_sha >>
release_channel: experimental
dist_tag: experimental
@ -674,14 +642,11 @@ workflows:
only:
- main
jobs:
- setup
- publish_prerelease:
name: Publish to Next channel
requires:
- setup
name: Publish to Canary channel
commit_sha: << pipeline.git.revision >>
release_channel: stable
dist_tag: "next"
dist_tag: "canary,next"
- publish_prerelease:
name: Publish to Experimental channel
requires:
@ -689,7 +654,7 @@ workflows:
# will sometimes fail if you try to concurrently publish two
# different versions of the same package, even if they use different
# dist tags.
- Publish to Next channel
- Publish to Canary channel
commit_sha: << pipeline.git.revision >>
release_channel: experimental
dist_tag: experimental

View File

@ -1,7 +1,7 @@
{
"packages": ["packages/react", "packages/react-dom", "packages/scheduler"],
"buildCommand": "download-build-in-codesandbox-ci",
"node": "14",
"node": "18",
"publishDirectory": {
"react": "build/oss-experimental/react",
"react-dom": "build/oss-experimental/react-dom",

View File

@ -8,15 +8,18 @@ const {
const restrictedGlobals = require('confusing-browser-globals');
const OFF = 0;
const WARNING = 1;
const ERROR = 2;
module.exports = {
extends: ['fbjs', 'prettier'],
extends: ['prettier'],
// Stop ESLint from looking for a configuration file in parent folders
root: true,
plugins: [
'babel',
'ft-flow',
'jest',
'no-for-of-loops',
'no-function-declare-after-return',
@ -24,7 +27,7 @@ module.exports = {
'react-internal',
],
parser: 'babel-eslint',
parser: 'hermes-eslint',
parserOptions: {
ecmaVersion: 9,
sourceType: 'script',
@ -33,6 +36,190 @@ module.exports = {
// We're stricter than the default config, mostly. We'll override a few rules
// and then enable some React specific ones.
rules: {
'ft-flow/array-style-complex-type': [OFF, 'verbose'],
'ft-flow/array-style-simple-type': [OFF, 'verbose'], // TODO should be WARNING
'ft-flow/boolean-style': ERROR,
'ft-flow/no-dupe-keys': ERROR,
'ft-flow/no-primitive-constructor-types': ERROR,
'ft-flow/no-types-missing-file-annotation': OFF, // TODO should be ERROR
'ft-flow/no-unused-expressions': ERROR,
// 'ft-flow/no-weak-types': WARNING,
// 'ft-flow/require-valid-file-annotation': ERROR,
'no-cond-assign': OFF,
'no-constant-condition': OFF,
'no-control-regex': OFF,
'no-debugger': ERROR,
'no-dupe-args': ERROR,
'no-dupe-keys': ERROR,
'no-duplicate-case': WARNING,
'no-empty-character-class': WARNING,
'no-empty': OFF,
'no-ex-assign': WARNING,
'no-extra-boolean-cast': WARNING,
'no-func-assign': ERROR,
'no-invalid-regexp': WARNING,
'no-irregular-whitespace': WARNING,
'no-negated-in-lhs': ERROR,
'no-obj-calls': ERROR,
'no-regex-spaces': WARNING,
'no-sparse-arrays': ERROR,
'no-unreachable': ERROR,
'use-isnan': ERROR,
'valid-jsdoc': OFF,
'block-scoped-var': OFF,
complexity: OFF,
'default-case': OFF,
'guard-for-in': OFF,
'no-alert': OFF,
'no-caller': ERROR,
'no-case-declarations': OFF,
'no-div-regex': OFF,
'no-else-return': OFF,
'no-empty-pattern': WARNING,
'no-eq-null': OFF,
'no-eval': ERROR,
'no-extend-native': WARNING,
'no-extra-bind': WARNING,
'no-fallthrough': WARNING,
'no-implicit-coercion': OFF,
'no-implied-eval': ERROR,
'no-invalid-this': OFF,
'no-iterator': OFF,
'no-labels': [ERROR, {allowLoop: true, allowSwitch: true}],
'no-lone-blocks': WARNING,
'no-loop-func': OFF,
'no-magic-numbers': OFF,
'no-multi-str': ERROR,
'no-native-reassign': [ERROR, {exceptions: ['Map', 'Set']}],
'no-new-func': ERROR,
'no-new': WARNING,
'no-new-wrappers': WARNING,
'no-octal-escape': WARNING,
'no-octal': WARNING,
'no-param-reassign': OFF,
'no-process-env': OFF,
'no-proto': ERROR,
'no-redeclare': OFF, // TODO should be WARNING?
'no-return-assign': OFF,
'no-script-url': ERROR,
'no-self-compare': WARNING,
'no-sequences': WARNING,
'no-throw-literal': ERROR,
'no-useless-call': WARNING,
'no-void': OFF,
'no-warning-comments': OFF,
'no-with': OFF,
radix: WARNING,
'vars-on-top': OFF,
yoda: OFF,
'init-declarations': OFF,
'no-catch-shadow': ERROR,
'no-delete-var': ERROR,
'no-label-var': WARNING,
'no-shadow-restricted-names': WARNING,
'no-undef-init': OFF,
'no-undef': ERROR,
'no-undefined': OFF,
'callback-return': OFF,
'global-require': OFF,
'handle-callback-err': OFF,
'no-mixed-requires': OFF,
'no-new-require': OFF,
'no-path-concat': OFF,
'no-process-exit': OFF,
'no-restricted-modules': OFF,
'no-sync': OFF,
camelcase: [OFF, {properties: 'always'}],
'consistent-this': [OFF, 'self'],
'func-names': OFF,
'func-style': [OFF, 'declaration'],
'id-length': OFF,
'id-match': OFF,
'max-depth': OFF,
'max-nested-callbacks': OFF,
'max-params': OFF,
'max-statements': OFF,
'new-cap': OFF,
'newline-after-var': OFF,
'no-array-constructor': ERROR,
'no-continue': OFF,
'no-inline-comments': OFF,
'no-lonely-if': OFF,
'no-negated-condition': OFF,
'no-nested-ternary': OFF,
'no-new-object': WARNING,
'no-plusplus': OFF,
'no-ternary': OFF,
'no-underscore-dangle': OFF,
'no-unneeded-ternary': WARNING,
'one-var': [WARNING, {initialized: 'never'}],
'operator-assignment': [WARNING, 'always'],
'require-jsdoc': OFF,
'sort-vars': OFF,
'spaced-comment': [
OFF,
'always',
{exceptions: ['jshint', 'jslint', 'eslint', 'global']},
],
'constructor-super': ERROR,
'no-class-assign': WARNING,
'no-const-assign': ERROR,
'no-dupe-class-members': ERROR,
'no-this-before-super': ERROR,
'object-shorthand': OFF,
'prefer-const': OFF,
'prefer-spread': OFF,
'prefer-reflect': OFF,
'prefer-template': OFF,
'require-yield': OFF,
'babel/generator-star-spacing': OFF,
'babel/new-cap': OFF,
'babel/array-bracket-spacing': OFF,
'babel/object-curly-spacing': OFF,
'babel/object-shorthand': OFF,
'babel/arrow-parens': OFF,
'babel/no-await-in-loop': OFF,
'babel/flow-object-type': OFF,
'react/display-name': OFF,
'react/forbid-prop-types': OFF,
'react/jsx-closing-bracket-location': OFF,
'react/jsx-curly-spacing': OFF,
'react/jsx-equals-spacing': WARNING,
'react/jsx-filename-extension': OFF,
'react/jsx-first-prop-new-line': OFF,
'react/jsx-handler-names': OFF,
'react/jsx-indent': OFF,
'react/jsx-indent-props': OFF,
'react/jsx-key': OFF,
'react/jsx-max-props-per-line': OFF,
'react/jsx-no-bind': OFF,
'react/jsx-no-duplicate-props': ERROR,
'react/jsx-no-literals': OFF,
'react/jsx-no-target-blank': OFF,
'react/jsx-pascal-case': OFF,
'react/jsx-sort-props': OFF,
'react/jsx-uses-vars': ERROR,
'react/no-comment-textnodes': OFF,
'react/no-danger': OFF,
'react/no-deprecated': OFF,
'react/no-did-mount-set-state': OFF,
'react/no-did-update-set-state': OFF,
'react/no-direct-mutation-state': OFF,
'react/no-multi-comp': OFF,
'react/no-render-return-value': OFF,
'react/no-set-state': OFF,
'react/no-string-refs': OFF,
'react/no-unknown-property': OFF,
'react/prefer-es6-class': OFF,
'react/prefer-stateless-function': OFF,
'react/prop-types': OFF,
'react/require-extension': OFF,
'react/require-optimization': OFF,
'react/require-render-return': OFF,
'react/sort-comp': OFF,
'react/sort-prop-types': OFF,
'accessor-pairs': OFF,
'brace-style': [ERROR, '1tbs'],
'consistent-return': OFF,
@ -49,9 +236,15 @@ module.exports = {
'no-inner-declarations': [ERROR, 'functions'],
'no-multi-spaces': ERROR,
'no-restricted-globals': [ERROR].concat(restrictedGlobals),
'no-restricted-syntax': [ERROR, 'WithStatement'],
'no-restricted-syntax': [
ERROR,
'WithStatement',
{
selector: 'MemberExpression[property.name=/^(?:substring|substr)$/]',
message: 'Prefer string.slice() over .substring() and .substr().',
},
],
'no-shadow': ERROR,
'no-unused-expressions': ERROR,
'no-unused-vars': [ERROR, {args: 'none'}],
'no-use-before-define': OFF,
'no-useless-concat': OFF,
@ -74,8 +267,6 @@ module.exports = {
// deal. But I turned it off because loading the plugin causes some obscure
// syntax error and it didn't seem worth investigating.
'max-len': OFF,
// Prettier forces semicolons in a few places
'flowtype/object-type-delimiter': OFF,
// React & JSX
// Our transforms set this automatically
@ -141,6 +332,7 @@ module.exports = {
'packages/react-native-renderer/**/*.js',
'packages/eslint-plugin-react-hooks/**/*.js',
'packages/jest-react/**/*.js',
'packages/internal-test-utils/**/*.js',
'packages/**/__tests__/*.js',
'packages/**/npm/*.js',
],
@ -166,7 +358,7 @@ module.exports = {
// We apply these settings to the source files that get compiled.
// They can use all features including JSX (but shouldn't use `var`).
files: esNextPaths,
parser: 'babel-eslint',
parser: 'hermes-eslint',
parserOptions: {
ecmaVersion: 8,
sourceType: 'module',
@ -204,14 +396,6 @@ module.exports = {
ERROR,
{isProductionUserAppCode: false},
],
// Disable accessibility checks
'jsx-a11y/aria-role': OFF,
'jsx-a11y/no-noninteractive-element-interactions': OFF,
'jsx-a11y/no-static-element-interactions': OFF,
'jsx-a11y/role-has-required-aria-props': OFF,
'jsx-a11y/no-noninteractive-tabindex': OFF,
'jsx-a11y/tabindex-no-positive': OFF,
},
},
{
@ -232,7 +416,6 @@ module.exports = {
{
files: [
'packages/react-native-renderer/**/*.js',
'packages/react-server-native-relay/**/*.js',
],
globals: {
nativeFabricUIManager: 'readonly',
@ -253,10 +436,71 @@ module.exports = {
},
],
env: {
browser: true,
es6: true,
node: true,
jest: true,
},
globals: {
$Call: 'readonly',
$ElementType: 'readonly',
$Flow$ModuleRef: 'readonly',
$FlowFixMe: 'readonly',
$Keys: 'readonly',
$NonMaybeType: 'readonly',
$PropertyType: 'readonly',
$ReadOnly: 'readonly',
$ReadOnlyArray: 'readonly',
$Shape: 'readonly',
AnimationFrameID: 'readonly',
// For Flow type annotation. Only `BigInt` is valid at runtime.
bigint: 'readonly',
BigInt: 'readonly',
Class: 'readonly',
ClientRect: 'readonly',
CopyInspectedElementPath: 'readonly',
DOMHighResTimeStamp: 'readonly',
EventListener: 'readonly',
Iterable: 'readonly',
Iterator: 'readonly',
JSONValue: 'readonly',
JSResourceReference: 'readonly',
MouseEventHandler: 'readonly',
PropagationPhases: 'readonly',
PropertyDescriptor: 'readonly',
React$AbstractComponent: 'readonly',
React$Component: 'readonly',
React$ComponentType: 'readonly',
React$Config: 'readonly',
React$Context: 'readonly',
React$Element: 'readonly',
React$ElementConfig: 'readonly',
React$ElementProps: 'readonly',
React$ElementRef: 'readonly',
React$ElementType: 'readonly',
React$Key: 'readonly',
React$Node: 'readonly',
React$Portal: 'readonly',
React$Ref: 'readonly',
React$StatelessFunctionalComponent: 'readonly',
ReadableStreamController: 'readonly',
RequestInfo: 'readonly',
RequestOptions: 'readonly',
ResponseState: 'readonly',
StoreAsGlobal: 'readonly',
symbol: 'readonly',
SyntheticEvent: 'readonly',
SyntheticMouseEvent: 'readonly',
Thenable: 'readonly',
TimeoutID: 'readonly',
WheelEventHandler: 'readonly',
spyOnDev: 'readonly',
spyOnDevAndProd: 'readonly',
spyOnProd: 'readonly',
__DEV__: 'readonly',
__EXPERIMENTAL__: 'readonly',
__EXTENSION__: 'readonly',
__PROFILE__: 'readonly',

View File

@ -9,7 +9,7 @@
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 debug-test --watch TestName`, open `chrome://inspect`, and press "Inspect".
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`).

View File

@ -1,24 +1,29 @@
name: Commit Artifacts for Facebook WWW
name: Commit Artifacts for Meta WWW and fbsource
on:
push:
branches: [main]
branches: [main, meta-www, meta-fbsource]
jobs:
download_artifacts:
runs-on: ubuntu-latest
outputs:
www_branch_count: ${{ steps.check_branches.outputs.www_branch_count }}
fbsource_branch_count: ${{ steps.check_branches.outputs.fbsource_branch_count }}
steps:
- uses: actions/setup-node@v3
with:
node-version: 18.x
- run: npm init -y
- run: npm install node-fetch@2
- uses: actions/checkout@v3
- name: "Check branches"
id: check_branches
run: |
echo "www_branch_count=$(git ls-remote --heads origin "refs/heads/meta-www" | wc -l)" >> "$GITHUB_OUTPUT"
echo "fbsource_branch_count=$(git ls-remote --heads origin "refs/heads/meta-fbsource" | wc -l)" >> "$GITHUB_OUTPUT"
- name: Download and unzip artifacts
uses: actions/github-script@v6
env:
CIRCLECI_TOKEN: ${{secrets.CIRCLECI_TOKEN_DIFFTRAIN}}
with:
script: |
const cp = require('child_process');
const fetch = require('node-fetch');
function sleep(ms) {
return new Promise(resolve => setTimeout(resolve, ms));
@ -64,10 +69,10 @@ jobs:
const ciBuildId = /\/facebook\/react\/([0-9]+)/.exec(
status.target_url,
)[1];
console.log(`CircleCI build id found: ${ciBuildId}`);
if (Number.parseInt(ciBuildId, 10) + '' === ciBuildId) {
artifactsUrl =
`https://circleci.com/api/v1.1/project/github/facebook/react/${ciBuildId}/artifacts`;
console.log(`Found artifactsUrl: ${artifactsUrl}`);
break spinloop;
} else {
throw new Error(`${ciBuildId} isn't a number`);
@ -86,13 +91,21 @@ jobs:
await sleep(60_000);
}
if (artifactsUrl != null) {
const res = await fetch(artifactsUrl);
const {CIRCLECI_TOKEN} = process.env;
const res = await fetch(artifactsUrl, {
headers: {
'Circle-Token': CIRCLECI_TOKEN
}
});
const data = await res.json();
if (!Array.isArray(data) && data.message != null) {
throw `CircleCI returned: ${data.message}`;
}
for (const artifact of data) {
if (artifact.path === 'build.tgz') {
console.log(`Downloading and unzipping ${artifact.url}`);
await execHelper(
`curl -L ${artifact.url} | tar -xvz`
`curl -L ${artifact.url} -H "Circle-Token: ${CIRCLECI_TOKEN}" | tar -xvz`
);
}
}
@ -102,9 +115,9 @@ jobs:
- name: Strip @license from eslint plugin and react-refresh
run: |
sed -i -e 's/ @license React*//' \
build/oss-stable/eslint-plugin-react-hooks/cjs/eslint-plugin-react-hooks.development.js \
build/oss-stable/react-refresh/cjs/react-refresh-babel.development.js
- name: Move relevant files into compiled
build/oss-experimental/eslint-plugin-react-hooks/cjs/eslint-plugin-react-hooks.development.js \
build/oss-experimental/react-refresh/cjs/react-refresh-babel.development.js
- name: Move relevant files for React in www into compiled
run: |
mkdir -p ./compiled
mkdir -p ./compiled/facebook-www
@ -117,7 +130,7 @@ jobs:
mv build/WARNINGS ./compiled/facebook-www/WARNINGS
# Copy eslint-plugin-react-hooks into facebook-www
mv build/oss-stable/eslint-plugin-react-hooks/cjs/eslint-plugin-react-hooks.development.js \
mv build/oss-experimental/eslint-plugin-react-hooks/cjs/eslint-plugin-react-hooks.development.js \
./compiled/facebook-www/eslint-plugin-react-hooks.js
# Copy unstable_server-external-runtime.js into facebook-www
@ -125,21 +138,46 @@ jobs:
./compiled/facebook-www/unstable_server-external-runtime.js
# Copy react-refresh-babel.development.js into babel-plugin-react-refresh
mv build/oss-stable/react-refresh/cjs/react-refresh-babel.development.js \
mv build/oss-experimental/react-refresh/cjs/react-refresh-babel.development.js \
./compiled/babel-plugin-react-refresh/index.js
ls -R ./compiled
- name: Add REVISION files
- name: Move relevant files for React in fbsource into compiled-rn
run: |
BASE_FOLDER='compiled-rn/facebook-fbsource/xplat/js'
mkdir -p ${BASE_FOLDER}/react-native-github/Libraries/Renderer/
mkdir -p ${BASE_FOLDER}/RKJSModules/vendor/{scheduler,react,react-is,react-test-renderer}/
# Move React Native renderer
mv build/react-native/implementations/ $BASE_FOLDER/react-native-github/Libraries/Renderer/
mv build/react-native/shims/ $BASE_FOLDER/react-native-github/Libraries/Renderer/
mv build/facebook-react-native/scheduler/cjs/ $BASE_FOLDER/RKJSModules/vendor/scheduler/
mv build/facebook-react-native/react/cjs/ $BASE_FOLDER/RKJSModules/vendor/react/
mv build/facebook-react-native/react-is/cjs/ $BASE_FOLDER/RKJSModules/vendor/react-is/
mv build/facebook-react-native/react-test-renderer/cjs/ $BASE_FOLDER/RKJSModules/vendor/react-test-renderer/
# Delete OSS renderer. OSS renderer is synced through internal script.
RENDERER_FOLDER=$BASE_FOLDER/react-native-github/Libraries/Renderer/implementations/
rm $RENDERER_FOLDER/ReactFabric-{dev,prod,profiling}.js
rm $RENDERER_FOLDER/ReactNativeRenderer-{dev,prod,profiling}.js
ls -R ./compiled
- name: Add REVISION file
run: |
echo ${{ github.sha }} >> ./compiled/facebook-www/REVISION
cp ./compiled/facebook-www/REVISION ./compiled/facebook-www/REVISION_TRANSFORMS
echo ${{ github.sha }} >> ./compiled-rn/facebook-fbsource/xplat/js/react-native-github/Libraries/Renderer/REVISION
- uses: actions/upload-artifact@v3
with:
name: compiled
path: compiled/
- uses: actions/upload-artifact@v3
with:
name: compiled-rn
path: compiled-rn/
commit_artifacts:
commit_www_artifacts:
needs: download_artifacts
if: ${{ (github.ref == 'refs/heads/main' && needs.download_artifacts.outputs.www_branch_count == '0') || github.ref == 'refs/heads/meta-www' }}
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
@ -152,15 +190,59 @@ jobs:
name: compiled
path: compiled/
- run: git status -u
- name: Check if only the REVISION file has changed
id: check_should_commit
run: |
if git status --porcelain | grep -qv '/REVISION$'; then
echo "should_commit=true" >> "$GITHUB_OUTPUT"
else
echo "should_commit=false" >> "$GITHUB_OUTPUT"
fi
- name: Commit changes to branch
if: steps.check_should_commit.outputs.should_commit == 'true'
uses: stefanzweifel/git-auto-commit-action@v4
with:
commit_message: |
${{ github.event.head_commit.message }}
DiffTrain build for [${{ github.sha }}](https://github.com/facebook/react/commit/${{ github.sha }})
[View git log for this commit](https://github.com/facebook/react/commits/${{ github.sha }})
branch: builds/facebook-www
commit_user_name: ${{ github.actor }}
commit_user_email: ${{ github.actor }}@users.noreply.github.com
create_branch: true
commit_fbsource_artifacts:
needs: download_artifacts
runs-on: ubuntu-latest
if: ${{ (github.ref == 'refs/heads/main' && needs.download_artifacts.outputs.fbsource_branch_count == '0') || github.ref == 'refs/heads/meta-fbsource' }}
steps:
- uses: actions/checkout@v3
with:
ref: main
repository: facebook/react-fbsource-import
token: ${{secrets.FBSOURCE_SYNC_PUSH_TOKEN}}
- name: Ensure clean directory
run: rm -rf compiled-rn
- uses: actions/download-artifact@v3
with:
name: compiled-rn
path: compiled-rn/
- run: git status -u
- name: Check if only the REVISION file has changed
id: check_should_commit
run: |
if git status --porcelain | grep -qv '/REVISION$'; then
echo "should_commit=true" >> "$GITHUB_OUTPUT"
else
echo "should_commit=false" >> "$GITHUB_OUTPUT"
fi
- name: Commit changes to branch
if: steps.check_should_commit.outputs.should_commit == 'true'
uses: stefanzweifel/git-auto-commit-action@v4
with:
commit_message: |
${{ github.event.head_commit.message }}
DiffTrain build for commit https://github.com/facebook/react/commit/${{ github.sha }}.
commit_user_name: ${{ github.actor }}
commit_user_email: ${{ github.actor }}@users.noreply.github.com

2
.nvmrc
View File

@ -1 +1 @@
v14.17.6
v16.19.1

View File

@ -8,8 +8,8 @@ module.exports = {
jsxBracketSameLine: true,
trailingComma: 'es5',
printWidth: 80,
parser: 'babel',
parser: 'flow',
arrowParens: 'avoid',
overrides: [
{
files: esNextPaths,

View File

@ -17,7 +17,7 @@
### Server Components (Experimental)
* Add support for `useId()` inside Server Components. ([@gnoff](https://github.com/gnoff)) in [#24172](https://github.com/facebook/react/pull/24172)
* Add support for `useId()` inside Server Components. ([@gnoff](https://github.com/gnoff) in [#24172](https://github.com/facebook/react/pull/24172))
## 18.1.0 (April 26, 2022)
@ -102,6 +102,10 @@ The existing `renderToString` method keeps working but is discouraged.
* **Layout Effects with Suspense**: When a tree re-suspends and reverts to a fallback, React will now clean up layout effects, and then re-create them when the content inside the boundary is shown again. This fixes an issue which prevented component libraries from correctly measuring layout when used with Suspense.
* **New JS Environment Requirements**: React now depends on modern browsers features including `Promise`, `Symbol`, and `Object.assign`. If you support older browsers and devices such as Internet Explorer which do not provide modern browser features natively or have non-compliant implementations, consider including a global polyfill in your bundled application.
### Scheduler (Experimental)
* Remove unstable `scheduler/tracing` API
## Notable Changes
### React
@ -193,6 +197,10 @@ The existing `renderToString` method keeps working but is discouraged.
* Fix a mistake in the Node loader. ([#22537](https://github.com/facebook/react/pull/22537) by [@btea](https://github.com/btea))
* Use `globalThis` instead of `window` for edge environments. ([#22777](https://github.com/facebook/react/pull/22777) by [@huozhi](https://github.com/huozhi))
### Scheduler (Experimental)
* Remove unstable `scheduler/tracing` API ([#20037](https://github.com/facebook/react/pull/20037) by [@bvaughn](https://github.com/bvaughn))
## 17.0.2 (March 22, 2021)
### React DOM

View File

@ -1,4 +1,4 @@
# [React](https://reactjs.org/) &middot; [![GitHub license](https://img.shields.io/badge/license-MIT-blue.svg)](https://github.com/facebook/react/blob/main/LICENSE) [![npm version](https://img.shields.io/npm/v/react.svg?style=flat)](https://www.npmjs.com/package/react) [![CircleCI Status](https://circleci.com/gh/facebook/react.svg?style=shield&circle-token=:circle-token)](https://circleci.com/gh/facebook/react) [![PRs Welcome](https://img.shields.io/badge/PRs-welcome-brightgreen.svg)](https://reactjs.org/docs/how-to-contribute.html#your-first-pull-request)
# [React](https://reactjs.org/) &middot; [![GitHub license](https://img.shields.io/badge/license-MIT-blue.svg)](https://github.com/facebook/react/blob/main/LICENSE) [![npm version](https://img.shields.io/npm/v/react.svg?style=flat)](https://www.npmjs.com/package/react) [![CircleCI Status](https://circleci.com/gh/facebook/react.svg?style=shield)](https://circleci.com/gh/facebook/react) [![PRs Welcome](https://img.shields.io/badge/PRs-welcome-brightgreen.svg)](https://reactjs.org/docs/how-to-contribute.html#your-first-pull-request)
React is a JavaScript library for building user interfaces.

View File

@ -7,12 +7,12 @@
//
// The @latest channel uses the version as-is, e.g.:
//
// 18.0.0
// 18.3.0
//
// The @next channel appends additional information, with the scheme
// The @canary channel appends additional information, with the scheme
// <version>-<label>-<commit_sha>, e.g.:
//
// 18.0.0-alpha-a1c2d3e4
// 18.3.0-canary-a1c2d3e4
//
// The @experimental channel doesn't include a version, only a date and a sha, e.g.:
//
@ -20,9 +20,13 @@
const ReactVersion = '18.3.0';
// The label used by the @next channel. Represents the upcoming release's
// stability. Could be "alpha", "beta", "rc", etc.
const nextChannelLabel = 'next';
// The label used by the @canary channel. Represents the upcoming release's
// stability. Most of the time, this will be "canary", but we may temporarily
// choose to change it to "alpha", "beta", "rc", etc.
//
// It only affects the label used in the version string. To customize the
// npm dist tags used during publish, refer to .circleci/config.yml.
const canaryChannelLabel = 'canary';
const stablePackages = {
'eslint-plugin-react-hooks': '5.0.0',
@ -40,14 +44,14 @@ const stablePackages = {
scheduler: '0.24.0',
};
// These packages do not exist in the @next or @latest channel, only
// These packages do not exist in the @canary or @latest channel, only
// @experimental. We don't use semver, just the commit sha, so this is just a
// list of package names instead of a map.
const experimentalPackages = [];
module.exports = {
ReactVersion,
nextChannelLabel,
canaryChannelLabel,
stablePackages,
experimentalPackages,
};

View File

@ -97,7 +97,7 @@ function row(result, baseSha, headSha) {
return rowArr.join(' | ');
}
(async function() {
(async function () {
// Use git locally to grab the commit which represents the place
// where the branches differ
@ -241,8 +241,9 @@ Comparing: ${baseSha}...${headSha}
## Critical size changes
Includes critical production bundles, as well as any change greater than ${CRITICAL_THRESHOLD *
100}%:
Includes critical production bundles, as well as any change greater than ${
CRITICAL_THRESHOLD * 100
}%:
${header}
${criticalResults.join('\n')}

View File

@ -5,12 +5,13 @@
"@babel/preset-env": "^7.10.4",
"@babel/preset-react": "^7.10.4",
"babel-loader": "^8.1.0",
"react": "link:../../build/node_modules/react",
"react-art": "link:../../build/node_modules/react-art/",
"react-dom": "link:../../build/node_modules/react-dom",
"react": "^18.2.0",
"react-art": "^18.2.0",
"react-dom": "^18.2.0",
"webpack": "^1.14.0"
},
"scripts": {
"prebuild": "cp -r ../../build/oss-experimental/* ./node_modules/",
"build": "webpack app.js bundle.js"
}
}

View File

@ -1007,6 +1007,11 @@ arrify@^1.0.0:
version "1.0.1"
resolved "https://registry.yarnpkg.com/arrify/-/arrify-1.0.1.tgz#898508da2226f380df904728456849c1501a4b0d"
art@^0.10.1:
version "0.10.3"
resolved "https://registry.yarnpkg.com/art/-/art-0.10.3.tgz#b01d84a968ccce6208df55a733838c96caeeaea2"
integrity sha512-HXwbdofRTiJT6qZX/FnchtldzJjS3vkLJxQilc3Xj+ma2MXjY4UAyQ0ls1XZYVnDvVIBiFZbC6QsvtW86TD6tQ==
asn1@~0.2.3:
version "0.2.3"
resolved "https://registry.yarnpkg.com/asn1/-/asn1-0.2.3.tgz#dac8787713c9966849fc8180777ebe9c1ddf3b86"
@ -1286,6 +1291,14 @@ core-util-is@~1.0.0:
version "1.0.2"
resolved "https://registry.yarnpkg.com/core-util-is/-/core-util-is-1.0.2.tgz#b5fd54220aa2bc5ab57aab7140c940754503c1a7"
create-react-class@^15.6.2:
version "15.7.0"
resolved "https://registry.yarnpkg.com/create-react-class/-/create-react-class-15.7.0.tgz#7499d7ca2e69bb51d13faf59bd04f0c65a1d6c1e"
integrity sha512-QZv4sFWG9S5RUvkTYWbflxeZX+JG7Cz0Tn33rQBJ+WFQTqTfUTjMjiv9tnfXazjsO5r0KhPs+AqCjyrQX6h2ng==
dependencies:
loose-envify "^1.3.1"
object-assign "^4.1.1"
cryptiles@2.x.x:
version "2.0.5"
resolved "https://registry.yarnpkg.com/cryptiles/-/cryptiles-2.0.5.tgz#3bdfecdc608147c1c67202fa291e7dca59eaa3b8"
@ -1761,7 +1774,7 @@ js-tokens@^3.0.0:
version "3.0.1"
resolved "https://registry.yarnpkg.com/js-tokens/-/js-tokens-3.0.1.tgz#08e9f132484a2c45a30907e9dc4d5567b7f114d7"
js-tokens@^4.0.0:
"js-tokens@^3.0.0 || ^4.0.0", js-tokens@^4.0.0:
version "4.0.0"
resolved "https://registry.yarnpkg.com/js-tokens/-/js-tokens-4.0.0.tgz#19203fb59991df98e3a287050d4647cdeaf32499"
integrity sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==
@ -1897,6 +1910,13 @@ loose-envify@^1.0.0:
dependencies:
js-tokens "^3.0.0"
loose-envify@^1.1.0, loose-envify@^1.3.1:
version "1.4.0"
resolved "https://registry.yarnpkg.com/loose-envify/-/loose-envify-1.4.0.tgz#71ee51fa7be4caec1a63839f7e682d8132d30caf"
integrity sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q==
dependencies:
js-tokens "^3.0.0 || ^4.0.0"
make-dir@^2.0.0:
version "2.1.0"
resolved "https://registry.yarnpkg.com/make-dir/-/make-dir-2.1.0.tgz#5f0310e18b8be898cc07009295a30ae41e91e6f5"
@ -2066,9 +2086,10 @@ oauth-sign@~0.8.1:
version "0.8.2"
resolved "https://registry.yarnpkg.com/oauth-sign/-/oauth-sign-0.8.2.tgz#46a6ab7f0aead8deae9ec0565780b7d4efeb9d43"
object-assign@^4.0.1, object-assign@^4.1.0:
object-assign@^4.0.1, object-assign@^4.1.0, object-assign@^4.1.1:
version "4.1.1"
resolved "https://registry.yarnpkg.com/object-assign/-/object-assign-4.1.1.tgz#2109adc7965887cfc05cbbd442cac8bfbb360863"
integrity sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==
object-keys@^1.0.11, object-keys@^1.0.12:
version "1.1.1"
@ -2251,17 +2272,30 @@ rc@^1.1.7:
minimist "^1.2.0"
strip-json-comments "~2.0.1"
"react-art@link:../../build/node_modules/react-art":
version "0.0.0"
uid ""
react-art@^18.2.0:
version "18.2.0"
resolved "https://registry.yarnpkg.com/react-art/-/react-art-18.2.0.tgz#73b3929b1a0ce781b088bce76186d3793f0106c5"
integrity sha512-HfSK9OBtPIpkdI4QZAyWSxCIbM/I7+nqjybxp2FLmiFS7RN+eCEvOY0KdPw+6//B1oIU31t2o35s5EEhe0Fodw==
dependencies:
art "^0.10.1"
create-react-class "^15.6.2"
loose-envify "^1.1.0"
scheduler "^0.23.0"
"react-dom@link:../../build/node_modules/react-dom":
version "0.0.0"
uid ""
react-dom@^18.2.0:
version "18.2.0"
resolved "https://registry.yarnpkg.com/react-dom/-/react-dom-18.2.0.tgz#22aaf38708db2674ed9ada224ca4aa708d821e3d"
integrity sha512-6IMTriUmvsjHUjNtEDudZfuDQUoWXVxKHhlEGSk81n4YFS+r/Kl99wXiwlVXtPBtJenozv2P+hxDsw9eA7Xo6g==
dependencies:
loose-envify "^1.1.0"
scheduler "^0.23.0"
"react@link:../../build/node_modules/react":
version "0.0.0"
uid ""
react@^18.2.0:
version "18.2.0"
resolved "https://registry.yarnpkg.com/react/-/react-18.2.0.tgz#555bd98592883255fa00de14f1151a917b5d77d5"
integrity sha512-/3IjMdb2L9QbBdWiW5e3P2/npwMBaU9mHCSCUzNln0ZCYbcfTsGbTJrU/kGemdH2IWmB2ioZ+zkxtmq6g09fGQ==
dependencies:
loose-envify "^1.1.0"
"readable-stream@^2.0.0 || ^1.1.13", readable-stream@^2.0.1, readable-stream@^2.0.2, readable-stream@^2.0.5, readable-stream@^2.1.4, readable-stream@^2.2.6:
version "2.2.6"
@ -2441,6 +2475,13 @@ safe-buffer@~5.1.1:
resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.1.2.tgz#991ec69d296e0313747d59bdfd2b745c35f8828d"
integrity sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==
scheduler@^0.23.0:
version "0.23.0"
resolved "https://registry.yarnpkg.com/scheduler/-/scheduler-0.23.0.tgz#ba8041afc3d30eb206a487b6b384002e4e61fdfe"
integrity sha512-CtuThmgHNg7zIZWAXi3AsyIzA3n4xx7aNyjwC2VJldO2LMVDhFK+63xGqq6CsJH4rTAt6/M+N4GhZiDYPx9eUw==
dependencies:
loose-envify "^1.1.0"
schema-utils@^2.6.5:
version "2.7.0"
resolved "https://registry.yarnpkg.com/schema-utils/-/schema-utils-2.7.0.tgz#17151f76d8eae67fbbf77960c33c676ad9f4efc7"

View File

@ -1998,7 +1998,7 @@
| `colSpan=(null)`| (initial, ssr error, ssr mismatch)| `<number: 1>` |
| `colSpan=(undefined)`| (initial, ssr error, ssr mismatch)| `<number: 1>` |
## `content` (on `<meta>` inside `<div>`)
## `content` (on `<meta>` inside `<head>`)
| Test Case | Flags | Result |
| --- | --- | --- |
| `content=(string)`| (changed)| `"a string"` |
@ -3348,6 +3348,81 @@
| `externalResourcesRequired=(null)`| (initial)| `<null>` |
| `externalResourcesRequired=(undefined)`| (initial)| `<null>` |
## `fetchPriority` (on `<img>` inside `<div>`)
| Test Case | Flags | Result |
| --- | --- | --- |
| `fetchPriority=(string)`| (changed)| `"high"` |
| `fetchPriority=(empty string)`| (initial)| `"auto"` |
| `fetchPriority=(array with string)`| (changed)| `"high"` |
| `fetchPriority=(empty array)`| (initial)| `"auto"` |
| `fetchPriority=(object)`| (initial)| `"auto"` |
| `fetchPriority=(numeric string)`| (initial)| `"auto"` |
| `fetchPriority=(-1)`| (initial)| `"auto"` |
| `fetchPriority=(0)`| (initial)| `"auto"` |
| `fetchPriority=(integer)`| (initial)| `"auto"` |
| `fetchPriority=(NaN)`| (initial, warning)| `"auto"` |
| `fetchPriority=(float)`| (initial)| `"auto"` |
| `fetchPriority=(true)`| (initial, warning)| `"auto"` |
| `fetchPriority=(false)`| (initial, warning)| `"auto"` |
| `fetchPriority=(string 'true')`| (initial)| `"auto"` |
| `fetchPriority=(string 'false')`| (initial)| `"auto"` |
| `fetchPriority=(string 'on')`| (initial)| `"auto"` |
| `fetchPriority=(string 'off')`| (initial)| `"auto"` |
| `fetchPriority=(symbol)`| (initial, warning)| `"auto"` |
| `fetchPriority=(function)`| (initial, warning)| `"auto"` |
| `fetchPriority=(null)`| (initial)| `"auto"` |
| `fetchPriority=(undefined)`| (initial)| `"auto"` |
## `fetchpriority` (on `<img>` inside `<div>`)
| Test Case | Flags | Result |
| --- | --- | --- |
| `fetchpriority=(string)`| (changed, warning)| `"high"` |
| `fetchpriority=(empty string)`| (initial, warning)| `"auto"` |
| `fetchpriority=(array with string)`| (changed, warning)| `"high"` |
| `fetchpriority=(empty array)`| (initial, warning)| `"auto"` |
| `fetchpriority=(object)`| (initial, warning)| `"auto"` |
| `fetchpriority=(numeric string)`| (initial, warning)| `"auto"` |
| `fetchpriority=(-1)`| (initial, warning)| `"auto"` |
| `fetchpriority=(0)`| (initial, warning)| `"auto"` |
| `fetchpriority=(integer)`| (initial, warning)| `"auto"` |
| `fetchpriority=(NaN)`| (initial, warning)| `"auto"` |
| `fetchpriority=(float)`| (initial, warning)| `"auto"` |
| `fetchpriority=(true)`| (initial, warning)| `"auto"` |
| `fetchpriority=(false)`| (initial, warning)| `"auto"` |
| `fetchpriority=(string 'true')`| (initial, warning)| `"auto"` |
| `fetchpriority=(string 'false')`| (initial, warning)| `"auto"` |
| `fetchpriority=(string 'on')`| (initial, warning)| `"auto"` |
| `fetchpriority=(string 'off')`| (initial, warning)| `"auto"` |
| `fetchpriority=(symbol)`| (initial, warning)| `"auto"` |
| `fetchpriority=(function)`| (initial, warning)| `"auto"` |
| `fetchpriority=(null)`| (initial, warning)| `"auto"` |
| `fetchpriority=(undefined)`| (initial, warning)| `"auto"` |
## `fetchPriority` (on `<link>` inside `<div>`)
| Test Case | Flags | Result |
| --- | --- | --- |
| `fetchPriority=(string)`| (changed)| `"high"` |
| `fetchPriority=(empty string)`| (initial)| `"auto"` |
| `fetchPriority=(array with string)`| (changed)| `"high"` |
| `fetchPriority=(empty array)`| (initial)| `"auto"` |
| `fetchPriority=(object)`| (initial)| `"auto"` |
| `fetchPriority=(numeric string)`| (initial)| `"auto"` |
| `fetchPriority=(-1)`| (initial)| `"auto"` |
| `fetchPriority=(0)`| (initial)| `"auto"` |
| `fetchPriority=(integer)`| (initial)| `"auto"` |
| `fetchPriority=(NaN)`| (initial, warning)| `"auto"` |
| `fetchPriority=(float)`| (initial)| `"auto"` |
| `fetchPriority=(true)`| (initial, warning)| `"auto"` |
| `fetchPriority=(false)`| (initial, warning)| `"auto"` |
| `fetchPriority=(string 'true')`| (initial)| `"auto"` |
| `fetchPriority=(string 'false')`| (initial)| `"auto"` |
| `fetchPriority=(string 'on')`| (initial)| `"auto"` |
| `fetchPriority=(string 'off')`| (initial)| `"auto"` |
| `fetchPriority=(symbol)`| (initial, warning)| `"auto"` |
| `fetchPriority=(function)`| (initial, warning)| `"auto"` |
| `fetchPriority=(null)`| (initial)| `"auto"` |
| `fetchPriority=(undefined)`| (initial)| `"auto"` |
## `fill` (on `<path>` inside `<svg>`)
| Test Case | Flags | Result |
| --- | --- | --- |
@ -5048,7 +5123,7 @@
| `htmlFor=(null)`| (initial)| `<empty string>` |
| `htmlFor=(undefined)`| (initial)| `<empty string>` |
## `http-equiv` (on `<meta>` inside `<div>`)
## `http-equiv` (on `<meta>` inside `<head>`)
| Test Case | Flags | Result |
| --- | --- | --- |
| `http-equiv=(string)`| (changed, warning)| `"a string"` |
@ -5073,7 +5148,7 @@
| `http-equiv=(null)`| (initial, warning)| `<empty string>` |
| `http-equiv=(undefined)`| (initial, warning)| `<empty string>` |
## `httpEquiv` (on `<meta>` inside `<div>`)
## `httpEquiv` (on `<meta>` inside `<head>`)
| Test Case | Flags | Result |
| --- | --- | --- |
| `httpEquiv=(string)`| (changed)| `"a string"` |
@ -6123,6 +6198,31 @@
| `lang=(null)`| (initial)| `<empty string>` |
| `lang=(undefined)`| (initial)| `<empty string>` |
## `lang` (on `<html>` inside `<document>`)
| Test Case | Flags | Result |
| --- | --- | --- |
| `lang=(string)`| (changed, ssr mismatch)| `"a string"` |
| `lang=(empty string)`| (initial)| `<empty string>` |
| `lang=(array with string)`| (changed, ssr mismatch)| `"string"` |
| `lang=(empty array)`| (initial)| `<empty string>` |
| `lang=(object)`| (changed, ssr mismatch)| `"result of toString()"` |
| `lang=(numeric string)`| (changed, ssr mismatch)| `"42"` |
| `lang=(-1)`| (changed, ssr mismatch)| `"-1"` |
| `lang=(0)`| (changed, ssr mismatch)| `"0"` |
| `lang=(integer)`| (changed, ssr mismatch)| `"1"` |
| `lang=(NaN)`| (changed, warning, ssr mismatch)| `"NaN"` |
| `lang=(float)`| (changed, ssr mismatch)| `"99.99"` |
| `lang=(true)`| (initial, warning)| `<empty string>` |
| `lang=(false)`| (initial, warning)| `<empty string>` |
| `lang=(string 'true')`| (changed, ssr mismatch)| `"true"` |
| `lang=(string 'false')`| (changed, ssr mismatch)| `"false"` |
| `lang=(string 'on')`| (changed, ssr mismatch)| `"on"` |
| `lang=(string 'off')`| (changed, ssr mismatch)| `"off"` |
| `lang=(symbol)`| (initial, warning)| `<empty string>` |
| `lang=(function)`| (initial, warning)| `<empty string>` |
| `lang=(null)`| (initial)| `<empty string>` |
| `lang=(undefined)`| (initial)| `<empty string>` |
## `length` (on `<div>` inside `<div>`)
| Test Case | Flags | Result |
| --- | --- | --- |
@ -11298,6 +11398,56 @@
| `transform=(null)`| (initial)| `[]` |
| `transform=(undefined)`| (initial)| `[]` |
## `transform-origin` (on `<svg>` inside `<div>`)
| Test Case | Flags | Result |
| --- | --- | --- |
| `transform-origin=(string)`| (changed, warning)| `"a string"` |
| `transform-origin=(empty string)`| (changed, warning)| `<empty string>` |
| `transform-origin=(array with string)`| (changed, warning)| `"string"` |
| `transform-origin=(empty array)`| (changed, warning)| `<empty string>` |
| `transform-origin=(object)`| (changed, warning)| `"result of toString()"` |
| `transform-origin=(numeric string)`| (changed, warning)| `"42"` |
| `transform-origin=(-1)`| (changed, warning)| `"-1"` |
| `transform-origin=(0)`| (changed, warning)| `"0"` |
| `transform-origin=(integer)`| (changed, warning)| `"1"` |
| `transform-origin=(NaN)`| (changed, warning)| `"NaN"` |
| `transform-origin=(float)`| (changed, warning)| `"99.99"` |
| `transform-origin=(true)`| (initial, warning)| `<null>` |
| `transform-origin=(false)`| (initial, warning)| `<null>` |
| `transform-origin=(string 'true')`| (changed, warning)| `"true"` |
| `transform-origin=(string 'false')`| (changed, warning)| `"false"` |
| `transform-origin=(string 'on')`| (changed, warning)| `"on"` |
| `transform-origin=(string 'off')`| (changed, warning)| `"off"` |
| `transform-origin=(symbol)`| (initial, warning)| `<null>` |
| `transform-origin=(function)`| (initial, warning)| `<null>` |
| `transform-origin=(null)`| (initial, warning)| `<null>` |
| `transform-origin=(undefined)`| (initial, warning)| `<null>` |
## `transformOrigin` (on `<svg>` inside `<div>`)
| Test Case | Flags | Result |
| --- | --- | --- |
| `transformOrigin=(string)`| (changed)| `"a string"` |
| `transformOrigin=(empty string)`| (changed)| `<empty string>` |
| `transformOrigin=(array with string)`| (changed)| `"string"` |
| `transformOrigin=(empty array)`| (changed)| `<empty string>` |
| `transformOrigin=(object)`| (changed)| `"result of toString()"` |
| `transformOrigin=(numeric string)`| (changed)| `"42"` |
| `transformOrigin=(-1)`| (changed)| `"-1"` |
| `transformOrigin=(0)`| (changed)| `"0"` |
| `transformOrigin=(integer)`| (changed)| `"1"` |
| `transformOrigin=(NaN)`| (changed, warning)| `"NaN"` |
| `transformOrigin=(float)`| (changed)| `"99.99"` |
| `transformOrigin=(true)`| (initial, warning)| `<null>` |
| `transformOrigin=(false)`| (initial, warning)| `<null>` |
| `transformOrigin=(string 'true')`| (changed)| `"true"` |
| `transformOrigin=(string 'false')`| (changed)| `"false"` |
| `transformOrigin=(string 'on')`| (changed)| `"on"` |
| `transformOrigin=(string 'off')`| (changed)| `"off"` |
| `transformOrigin=(symbol)`| (initial, warning)| `<null>` |
| `transformOrigin=(function)`| (initial, warning)| `<null>` |
| `transformOrigin=(null)`| (initial)| `<null>` |
| `transformOrigin=(undefined)`| (initial)| `<null>` |
## `type` (on `<button>` inside `<div>`)
| Test Case | Flags | Result |
| --- | --- | --- |
@ -12401,23 +12551,23 @@
## `viewTarget` (on `<view>` inside `<svg>`)
| Test Case | Flags | Result |
| --- | --- | --- |
| `viewTarget=(string)`| (changed, ssr mismatch)| `"a string"` |
| `viewTarget=(empty string)`| (changed, ssr mismatch)| `<empty string>` |
| `viewTarget=(array with string)`| (changed, ssr mismatch)| `"string"` |
| `viewTarget=(empty array)`| (changed, ssr mismatch)| `<empty string>` |
| `viewTarget=(object)`| (changed, ssr mismatch)| `"result of toString()"` |
| `viewTarget=(numeric string)`| (changed, ssr mismatch)| `"42"` |
| `viewTarget=(-1)`| (changed, ssr mismatch)| `"-1"` |
| `viewTarget=(0)`| (changed, ssr mismatch)| `"0"` |
| `viewTarget=(integer)`| (changed, ssr mismatch)| `"1"` |
| `viewTarget=(NaN)`| (changed, warning, ssr mismatch)| `"NaN"` |
| `viewTarget=(float)`| (changed, ssr mismatch)| `"99.99"` |
| `viewTarget=(string)`| (changed)| `"a string"` |
| `viewTarget=(empty string)`| (changed)| `<empty string>` |
| `viewTarget=(array with string)`| (changed)| `"string"` |
| `viewTarget=(empty array)`| (changed)| `<empty string>` |
| `viewTarget=(object)`| (changed)| `"result of toString()"` |
| `viewTarget=(numeric string)`| (changed)| `"42"` |
| `viewTarget=(-1)`| (changed)| `"-1"` |
| `viewTarget=(0)`| (changed)| `"0"` |
| `viewTarget=(integer)`| (changed)| `"1"` |
| `viewTarget=(NaN)`| (changed, warning)| `"NaN"` |
| `viewTarget=(float)`| (changed)| `"99.99"` |
| `viewTarget=(true)`| (initial, warning)| `<null>` |
| `viewTarget=(false)`| (initial, warning)| `<null>` |
| `viewTarget=(string 'true')`| (changed, ssr mismatch)| `"true"` |
| `viewTarget=(string 'false')`| (changed, ssr mismatch)| `"false"` |
| `viewTarget=(string 'on')`| (changed, ssr mismatch)| `"on"` |
| `viewTarget=(string 'off')`| (changed, ssr mismatch)| `"off"` |
| `viewTarget=(string 'true')`| (changed)| `"true"` |
| `viewTarget=(string 'false')`| (changed)| `"false"` |
| `viewTarget=(string 'on')`| (changed)| `"on"` |
| `viewTarget=(string 'off')`| (changed)| `"off"` |
| `viewTarget=(symbol)`| (initial, warning)| `<null>` |
| `viewTarget=(function)`| (initial, warning)| `<null>` |
| `viewTarget=(null)`| (initial)| `<null>` |

View File

@ -8,7 +8,7 @@
## Instructions
`yarn build --type=UMD_DEV react/index,react-dom && cd fixtures/attribute-behavior && yarn install && yarn start`
`yarn build --type=UMD_DEV react/index,react-dom && cd fixtures/attribute-behavior && yarn install && yarn dev`
## Interpretation

View File

@ -11,9 +11,9 @@
"react-virtualized": "^9.9.0"
},
"scripts": {
"prestart":
"cp ../../build/node_modules/react/umd/react.development.js public/ && cp ../../build/node_modules/react-dom/umd/react-dom.development.js public/ && cp ../../build/node_modules/react-dom/umd/react-dom-server-legacy.browser.development.js public/",
"start": "react-scripts start",
"predev":
"cp ../../build/oss-experimental/react/umd/react.development.js public/ && cp ../../build/oss-experimental/react-dom/umd/react-dom.development.js public/ && cp ../../build/oss-experimental/react-dom/umd/react-dom-server-legacy.browser.development.js public/",
"dev": "react-scripts start",
"build": "react-scripts build",
"test": "react-scripts test --env=jsdom",
"eject": "react-scripts eject"

View File

@ -237,6 +237,8 @@ function getRenderedAttributeValue(
return document.createElementNS('http://www.w3.org/2000/svg', 'svg');
} else if (containerTagName === 'document') {
return document.implementation.createHTMLDocument('');
} else if (containerTagName === 'head') {
return document.implementation.createHTMLDocument('').head;
} else {
return document.createElement(containerTagName);
}
@ -282,12 +284,12 @@ function getRenderedAttributeValue(
try {
let container = createContainer();
renderer.render(react.createElement(tagName, baseProps), container);
defaultValue = read(container.firstChild);
defaultValue = read(container.lastChild);
canonicalDefaultValue = getCanonicalizedValue(defaultValue);
container = createContainer();
renderer.render(react.createElement(tagName, props), container);
result = read(container.firstChild);
result = read(container.lastChild);
canonicalResult = getCanonicalizedValue(result);
didWarn = _didWarn;
didError = false;
@ -308,6 +310,12 @@ function getRenderedAttributeValue(
);
container = createContainer();
container.innerHTML = html;
} else if (containerTagName === 'head') {
const html = serverRenderer.renderToString(
react.createElement(tagName, props)
);
container = createContainer();
container.innerHTML = html;
} else {
const html = serverRenderer.renderToString(
react.createElement(
@ -764,7 +772,7 @@ class App extends React.Component {
ReactDOMStable:
'https://unpkg.com/react-dom@latest/umd/react-dom.development.js',
ReactDOMServerStable:
'https://unpkg.com/react-dom@latest/umd/react-dom-server.browser.development.js',
'https://unpkg.com/react-dom@latest/umd/react-dom-server-legacy.browser.development.js',
ReactNext: '/react.development.js',
ReactDOMNext: '/react-dom.development.js',
ReactDOMServerNext: '/react-dom-server-legacy.browser.development.js',
@ -902,8 +910,9 @@ class App extends React.Component {
let log = '';
for (let attribute of attributes) {
log += `## \`${attribute.name}\` (on \`<${attribute.tagName ||
'div'}>\` inside \`<${attribute.containerTagName || 'div'}>\`)\n`;
log += `## \`${attribute.name}\` (on \`<${
attribute.tagName || 'div'
}>\` inside \`<${attribute.containerTagName || 'div'}>\`)\n`;
log += '| Test Case | Flags | Result |\n';
log += '| --- | --- | --- |\n';

View File

@ -356,7 +356,7 @@ const attributes = [
},
{name: 'cols', tagName: 'textarea'},
{name: 'colSpan', containerTagName: 'tr', tagName: 'td'},
{name: 'content', tagName: 'meta'},
{name: 'content', containerTagName: 'head', tagName: 'meta'},
{name: 'contentEditable'},
{
name: 'contentScriptType',
@ -573,6 +573,24 @@ const attributes = [
tagName: 'path',
read: getSVGAttribute('externalResourcesRequired'),
},
{
name: 'fetchPriority',
overrideStringValue: 'high',
tagName: 'img',
read: getProperty('fetchPriority'),
},
{
name: 'fetchpriority',
overrideStringValue: 'high',
tagName: 'img',
read: getProperty('fetchPriority'),
},
{
name: 'fetchPriority',
overrideStringValue: 'high',
tagName: 'link',
read: getProperty('fetchPriority'),
},
{
name: 'fill',
containerTagName: 'svg',
@ -916,8 +934,13 @@ const attributes = [
{name: 'href', tagName: 'a', overrideStringValue: 'https://reactjs.com'},
{name: 'hrefLang', read: getAttribute('hreflang')},
{name: 'htmlFor', tagName: 'label'},
{name: 'http-equiv', tagName: 'meta', read: getProperty('httpEquiv')},
{name: 'httpEquiv', tagName: 'meta'},
{
name: 'http-equiv',
containerTagName: 'head',
tagName: 'meta',
read: getProperty('httpEquiv'),
},
{name: 'httpEquiv', containerTagName: 'head', tagName: 'meta'},
{name: 'icon', tagName: 'command', read: getAttribute('icon')},
{name: 'id'},
{name: 'ID', read: getProperty('id')},
@ -1058,6 +1081,7 @@ const attributes = [
{name: 'label', tagName: 'track'},
{name: 'LANG', read: getProperty('lang')},
{name: 'lang'},
{name: 'lang', containerTagName: 'document', tagName: 'html'},
{name: 'length', read: getAttribute('length')},
{
name: 'lengthAdjust',
@ -1963,6 +1987,16 @@ const attributes = [
overrideStringValue:
'translate(-10,-20) scale(2) rotate(45) translate(5,10)',
},
{
name: 'transform-origin',
tagName: 'svg',
read: getSVGAttribute('transform-origin'),
},
{
name: 'transformOrigin',
tagName: 'svg',
read: getSVGAttribute('transform-origin'),
},
{name: 'type', tagName: 'button', overrideStringValue: 'reset'},
{
name: 'type',

View File

@ -1 +0,0 @@
SKIP_PREFLIGHT_CHECK=true

View File

@ -1,77 +0,0 @@
{
"posts": [
{
"id": 1,
"userId": 2,
"title": "Welcome",
"body": "Hello, world!"
},
{
"id": 2,
"userId": 3,
"title": "A Guide to useEffect",
"body": "Let me tell you everything about useEffect"
},
{
"id": 3,
"userId": 1,
"title": "Here and There",
"body": "Browsers are smart"
}
],
"comments": [
{
"id": 1,
"body": "Hey there",
"postId": 1,
"userId": 1
},
{
"id": 2,
"body": "Welcome to the chat",
"postId": 1,
"userId": 2
},
{
"id": 3,
"body": "What editor/font are you using?",
"postId": 2,
"userId": 2
},
{
"id": 4,
"body": "It's always been hard",
"postId": 3,
"userId": 1
},
{
"id": 5,
"body": "It's still easy",
"postId": 3,
"userId": 2
}
],
"users": [{
"id": 1,
"name": "Sebastian",
"bioId": 10
}, {
"id": 2,
"name": "Sophie",
"bioId": 20
}, {
"id": 3,
"name": "Dan",
"bioId": 30
}],
"bios": [{
"id": 10,
"text": "I like European movies"
}, {
"id": 20,
"text": "I like math puzzles"
}, {
"id": 30,
"text": "I like reading twitter"
}]
}

View File

@ -1,14 +0,0 @@
/**
* Copyright (c) Meta Platforms, Inc. and affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/
module.exports = (req, res, next) => {
if (req.query.delay) {
setTimeout(next, Number(req.query.delay));
} else {
next();
}
};

View File

@ -1,37 +0,0 @@
{
"name": "blocks",
"version": "0.1.0",
"private": true,
"proxy": "http://localhost:3001/",
"dependencies": {
"concurrently": "^5.2.0",
"json-server": "^0.16.1",
"react": "^16.13.1",
"react-dom": "^16.13.1",
"react-scripts": "3.4.1"
},
"scripts": {
"prestart": "cp -r ../../build/node_modules/* ./node_modules/",
"prebuild": "cp -r ../../build/node_modules/* ./node_modules/",
"start": "concurrently \"npm run start:client\" \"npm run start:api\"",
"start:api": "json-server --watch db.json --port 3001 --delay 1000 --middlewares delay.js",
"start:client": "react-scripts start",
"build": "react-scripts build",
"eject": "react-scripts eject"
},
"eslintConfig": {
"extends": "react-app"
},
"browserslist": {
"production": [
">0.2%",
"not dead",
"not op_mini all"
],
"development": [
"last 1 chrome version",
"last 1 firefox version",
"last 1 safari version"
]
}
}

View File

@ -1,12 +0,0 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<title>Blocks Fixture</title>
</head>
<body>
<noscript>You need to enable JavaScript to run this app.</noscript>
<div id="root"></div>
</body>
</html>

View File

@ -1,105 +0,0 @@
/**
* Copyright (c) Meta Platforms, Inc. and affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/
import React, {
useReducer,
useEffect,
unstable_useTransition as useTransition,
useCallback,
useMemo,
Suspense,
} from 'react';
import {createCache, CacheProvider} from 'react/unstable-cache';
import {RouterProvider} from './client/RouterContext';
// TODO: can't really import a server component on the client.
import App from './server/App';
const initialUrl = window.location.pathname;
const initialState = {
// TODO: use this for invalidation.
cache: createCache(),
url: initialUrl,
pendingUrl: initialUrl,
root: <App route={initialUrl} />,
};
function reducer(state, action) {
switch (action.type) {
case 'startNavigation':
return {
...state,
pendingUrl: action.url,
};
case 'completeNavigation':
// TODO: cancel previous fetch?
return {
...state,
url: action.url,
pendingUrl: action.url,
root: action.root,
};
default:
throw new Error();
}
}
function Router() {
const [state, dispatch] = useReducer(reducer, initialState);
const [startTransition, isPending] = useTransition({
timeoutMs: 1500,
});
useEffect(() => {
document.body.style.cursor = isPending ? 'wait' : '';
}, [isPending]);
const navigate = useCallback(
url => {
startTransition(() => {
// TODO: Here, There, and Everywhere.
// TODO: Instant Transitions, somehow.
dispatch({
type: 'completeNavigation',
root: <App route={url} />,
url,
});
});
dispatch({
type: 'startNavigation',
url,
});
},
[startTransition]
);
useEffect(() => {
const listener = () => {
navigate(window.location.pathname);
};
window.addEventListener('popstate', listener);
return () => window.removeEventListener('popstate', listener);
}, [navigate]);
const routeContext = useMemo(
() => ({
pendingUrl: state.pendingUrl,
url: state.url,
navigate,
}),
[state.url, state.pendingUrl, navigate]
);
return (
<Suspense fallback={<h2>Loading...</h2>}>
<CacheProvider value={state.cache}>
<RouterProvider value={routeContext}>{state.root}</RouterProvider>
</CacheProvider>
</Suspense>
);
}
export default Router;

View File

@ -1,25 +0,0 @@
/**
* Copyright (c) Meta Platforms, Inc. and affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/
import * as React from 'react';
import {useRouter} from './RouterContext';
export default function Link({to, children, ...rest}) {
const {navigate} = useRouter();
return (
<a
href={to}
onClick={e => {
e.preventDefault();
window.history.pushState(null, null, to);
navigate(to);
}}
{...rest}>
{children}
</a>
);
}

View File

@ -1,21 +0,0 @@
/**
* Copyright (c) Meta Platforms, Inc. and affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/
/* eslint-disable import/first */
import * as React from 'react';
import {TabBar, TabLink} from '../client/TabNav';
export default function ProfileNav({userId}) {
// TODO: Don't hardcode ID.
return (
<TabBar>
<TabLink to={`/profile/${userId}`}>Timeline</TabLink>
<TabLink to={`/profile/${userId}/bio`}>Bio</TabLink>
</TabBar>
);
}

View File

@ -1,9 +0,0 @@
import {createContext, useContext} from 'react';
const RouterContext = createContext(null);
export const RouterProvider = RouterContext.Provider;
export function useRouter() {
return useContext(RouterContext);
}

View File

@ -1,31 +0,0 @@
/**
* Copyright (c) Meta Platforms, Inc. and affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/
import * as React from 'react';
import {TabBar, TabLink} from './TabNav';
// TODO: Error Boundaries.
function MainTabNav() {
return (
<TabBar>
<TabLink to="/">Home</TabLink>
<TabLink to="/profile/3" partial={true}>
Profile
</TabLink>
</TabBar>
);
}
export default function Shell({children}) {
return (
<>
<MainTabNav />
{children}
</>
);
}

View File

@ -1,50 +0,0 @@
/**
* Copyright (c) Meta Platforms, Inc. and affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/
import * as React from 'react';
import Link from './Link';
import {useRouter} from './RouterContext';
export function TabBar({children}) {
return (
<div
style={{
border: '1px solid #aaa',
padding: 20,
marginBottom: 20,
width: 500,
}}>
{children}
</div>
);
}
export function TabLink({to, partial, children}) {
const {pendingUrl: activeUrl} = useRouter();
const active = partial ? activeUrl.startsWith(to) : activeUrl === to;
if (active) {
return (
<b
style={{
display: 'inline-block',
marginRight: 20,
}}>
{children}
</b>
);
}
return (
<Link
style={{
display: 'inline-block',
marginRight: 20,
}}
to={to}>
{children}
</Link>
);
}

View File

@ -1,8 +0,0 @@
body {
font-family: Helvetica;
padding-left: 10px;
}
* {
box-sizing: border-box;
}

View File

@ -1,13 +0,0 @@
/**
* Copyright (c) Meta Platforms, Inc. and affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/
import React from 'react';
import {createRoot} from 'react-dom/client';
import './index.css';
import Router from './Router';
createRoot(document.getElementById('root')).render(<Router />);

View File

@ -1,28 +0,0 @@
/**
* Copyright (c) Meta Platforms, Inc. and affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/
/* eslint-disable import/first */
import * as React from 'react';
import {matchRoute} from './ServerRouter';
import FeedPage from './FeedPage';
import ProfilePage from './ProfilePage';
// TODO: Replace with asset reference.
import Shell from '../client/Shell';
// TODO: Router component?
const AppRoutes = {
'/': props => <FeedPage {...props} key="home" />,
'/profile/:userId/*': props => (
<ProfilePage {...props} key={`profile-${props.userId}`} />
),
};
export default function App(props) {
const match = matchRoute(props, AppRoutes);
return <Shell>{match}</Shell>;
}

View File

@ -1,31 +0,0 @@
/**
* Copyright (c) Meta Platforms, Inc. and affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/
/* eslint-disable import/first */
import * as React from 'react';
import {fetch} from 'react-fetch';
// TODO: Replace with asset reference.
import Link from '../client/Link';
export default function Comments({postId}) {
const comments = fetch(`/comments?postId=${postId}&_expand=user`).json();
return (
<>
<h5>Comments</h5>
<ul>
{comments.slice(0, 5).map(comment => (
<li key={comment.id}>
{comment.body}
{' • '}
<Link to={`/profile/${comment.user.id}`}>{comment.user.name}</Link>
</li>
))}
</ul>
</>
);
}

View File

@ -1,21 +0,0 @@
/**
* Copyright (c) Meta Platforms, Inc. and affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/
/* eslint-disable import/first */
import * as React from 'react';
import {fetch} from 'react-fetch';
import PostList from './PostList';
export default function Feed() {
const posts = fetch('/posts?_expand=user').json();
return (
<>
<h2>Feed</h2>
<PostList posts={posts} />
</>
);
}

View File

@ -1,20 +0,0 @@
/**
* Copyright (c) Meta Platforms, Inc. and affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/
/* eslint-disable import/first */
import * as React from 'react';
import {Suspense} from 'react';
import PostGlimmer from './PostGlimmer';
import Feed from './Feed';
export default function FeedPage() {
return (
<Suspense fallback={<PostGlimmer />}>
<Feed />
</Suspense>
);
}

View File

@ -1,39 +0,0 @@
/**
* Copyright (c) Meta Platforms, Inc. and affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/
/* eslint-disable import/first */
import * as React from 'react';
import {Suspense} from 'react';
import Comments from './Comments';
// TODO: Replace with asset reference.
import Link from '../client/Link';
export default function Post({post}) {
return (
<div
style={{
border: '1px solid #aaa',
borderRadius: 10,
marginBottom: 20,
padding: 20,
maxWidth: 500,
}}>
<h4 style={{marginTop: 0}}>
{post.title}
{' by '}
<Link to={`/profile/${post.user.id}`}>{post.user.name}</Link>
</h4>
<p>{post.body}</p>
<Suspense
fallback={<h5>Loading comments...</h5>}
unstable_avoidThisFallback={true}>
<Comments postId={post.id} />
</Suspense>
</div>
);
}

View File

@ -1,56 +0,0 @@
/**
* Copyright (c) Meta Platforms, Inc. and affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/
/* eslint-disable import/first */
import * as React from 'react';
export default function PostGlimmer() {
return (
<div
style={{
border: '1px solid #aaa',
borderRadius: 10,
marginBottom: 20,
padding: 20,
maxWidth: 500,
height: 180,
}}>
<div
style={{
marginBottom: 20,
width: '50%',
height: 20,
background: '#ddd',
}}
/>
<div
style={{
marginBottom: 20,
width: '60%',
height: 20,
background: '#eee',
}}
/>
<div
style={{
marginBottom: 20,
width: '50%',
height: 20,
background: '#eee',
}}
/>
<div
style={{
marginBottom: 20,
width: '60%',
height: 20,
background: '#eee',
}}
/>
</div>
);
}

View File

@ -1,28 +0,0 @@
/**
* Copyright (c) Meta Platforms, Inc. and affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/
/* eslint-disable import/first */
import * as React from 'react';
import {Suspense, unstable_SuspenseList as SuspenseList} from 'react';
import {preload} from 'react-fetch';
import PostGlimmer from './PostGlimmer';
import Post from './Post';
export default function PostList({posts}) {
return (
<SuspenseList revealOrder="forwards" tail="collapsed">
{posts.map(post => {
preload(`/comments?postId=${post.id}&_expand=user`);
return (
<Suspense key={post.id} fallback={<PostGlimmer />}>
<Post post={post} />
</Suspense>
);
})}
</SuspenseList>
);
}

View File

@ -1,21 +0,0 @@
/**
* Copyright (c) Meta Platforms, Inc. and affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/
/* eslint-disable import/first */
import * as React from 'react';
import {fetch} from 'react-fetch';
export default function ProfileBio({userId}) {
const user = fetch(`/users/${userId}`).json();
const bio = fetch(`/bios/${user.bioId}`).json().text;
return (
<>
<h3>{user.name}'s Bio</h3>
<p>{bio}</p>
</>
);
}

View File

@ -1,34 +0,0 @@
/**
* Copyright (c) Meta Platforms, Inc. and affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/
import * as React from 'react';
import {Suspense} from 'react';
import {fetch} from 'react-fetch';
import {matchRoute} from './ServerRouter';
import ProfileTimeline from './ProfileTimeline';
import ProfileBio from './ProfileBio';
// TODO: Replace with asset reference.
import ProfileNav from '../client/ProfileNav';
// TODO: Router component?
const ProfileRoutes = {
'/': props => <ProfileTimeline {...props} key="timeline" />,
'/bio': props => <ProfileBio {...props} key="bio" />,
};
export default function ProfilePage(props) {
const user = fetch(`/users/${props.userId}`).json();
const match = matchRoute(props, ProfileRoutes);
return (
<>
<h2>{user.name}</h2>
<ProfileNav userId={user.id} />
<Suspense fallback={<h3>Loading...</h3>}>{match}</Suspense>
</>
);
}

View File

@ -1,16 +0,0 @@
/**
* Copyright (c) Meta Platforms, Inc. and affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/
/* eslint-disable import/first */
import * as React from 'react';
import {fetch} from 'react-fetch';
import PostList from './PostList';
export default function ProfileTimeline({userId}) {
const posts = fetch(`/posts?userId=${userId}&_expand=user`).json();
return <PostList posts={posts} />;
}

View File

@ -1,54 +0,0 @@
/**
* Copyright (c) Meta Platforms, Inc. and affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/
/* eslint-disable import/first */
function tryMatch(props, def) {
const defSegments = def.split('/').filter(Boolean);
const routeSegments = props.route.split('/').filter(Boolean);
let innerProps = {...props};
while (routeSegments.length > 0) {
if (defSegments.length === 0) {
return null;
}
const urlSegment = routeSegments.shift();
const defSegment = defSegments.shift();
if (urlSegment === defSegment) {
continue;
}
if (defSegment[0] === ':') {
innerProps[defSegment.slice(1)] = urlSegment;
continue;
}
if (defSegment === '*') {
innerProps.route = '/' + urlSegment + routeSegments.join('/');
return innerProps;
}
return null;
}
if (defSegments.length === 0) {
return innerProps;
}
if (defSegments.length === 1 && defSegments[0] === '*') {
innerProps.route = '/';
return innerProps;
}
return null;
}
export function matchRoute(props, defs) {
for (let def in defs) {
if (!defs.hasOwnProperty(def)) {
continue;
}
const innerProps = tryMatch(props, def);
if (innerProps) {
const match = defs[def](innerProps);
return match;
}
}
throw Error('Not found.');
}

File diff suppressed because it is too large Load Diff

View File

@ -11,8 +11,8 @@
"victory": "^0.25.6"
},
"scripts": {
"copy-source": "cp -r ../../../build/node_modules/* ./node_modules/",
"start": "react-scripts start",
"copy-source": "cp -r ../../../build/oss-experimental/* ./node_modules/",
"dev": "react-scripts start",
"build": "react-scripts build",
"test": "react-scripts test --env=jsdom",
"eject": "react-scripts eject"

View File

@ -22,7 +22,7 @@ class App extends PureComponent {
}
const multiplier = input.length !== 0 ? input.length : 1;
const complexity =
(parseInt(window.location.search.substring(1), 10) / 100) * 25 || 25;
(parseInt(window.location.search.slice(1), 10) / 100) * 25 || 25;
const data = _.range(5).map(t =>
_.range(complexity * multiplier).map((j, i) => {
return {

View File

@ -15,8 +15,8 @@
<script src="https://unpkg.com/scheduler@canary/umd/scheduler-tracing.development.js"></script>
<script src="https://unpkg.com/react@canary/umd/react.development.js"></script>
<script src="https://unpkg.com/react-dom@canary/umd/react-dom.development.js"></script>
<script src="https://unpkg.com/react-cache@next/umd/react-cache.development.js"></script>
<script src="https://unpkg.com/react-cache@canary/umd/react-cache.development.js"></script>
<!-- Don't use this in production: -->
<script src="https://unpkg.com/babel-standalone@6/babel.min.js"></script>
</head>
@ -38,4 +38,4 @@
Learn more at https://reactjs.org/docs/getting-started.html
-->
</body>
</html>
</html>

View File

@ -11,12 +11,12 @@
__REACT_DEVTOOLS_GLOBAL_HOOK__ = parent.__REACT_DEVTOOLS_GLOBAL_HOOK__;
</script>
<script src="https://unpkg.com/scheduler@next/umd/scheduler.development.js"></script>
<script src="https://unpkg.com/scheduler@next/umd/scheduler-tracing.development.js"></script>
<script src="https://unpkg.com/react@next/umd/react.development.js"></script>
<script src="https://unpkg.com/react-dom@next/umd/react-dom.development.js"></script>
<script src="https://unpkg.com/react-cache@next/umd/react-cache.development.js"></script>
<script src="https://unpkg.com/scheduler@canary/umd/scheduler.development.js"></script>
<script src="https://unpkg.com/scheduler@canary/umd/scheduler-tracing.development.js"></script>
<script src="https://unpkg.com/react@canary/umd/react.development.js"></script>
<script src="https://unpkg.com/react-dom@canary/umd/react-dom.development.js"></script>
<script src="https://unpkg.com/react-cache@canary/umd/react-cache.development.js"></script>
<!-- Don't use this in production: -->
<script src="https://unpkg.com/babel-standalone@6/babel.min.js"></script>
</head>
@ -38,4 +38,4 @@
Learn more at https://reactjs.org/docs/getting-started.html
-->
</body>
</html>
</html>

View File

@ -1,4 +1,4 @@
/* eslint-disable no-fallthrough, react/react-in-jsx-scope, react/jsx-no-undef */
/* eslint-disable react/react-in-jsx-scope, react/jsx-no-undef */
/* global React ReactCache ReactDOM SchedulerTracing ScheduleTracing */
const apps = [];

View File

@ -18,7 +18,7 @@ const DEPENDENCIES = [
['react-dom/umd/react-dom.development.js', 'react-dom.js'],
];
const BUILD_DIRECTORY = '../../../build/node_modules/';
const BUILD_DIRECTORY = '../../../build/oss-experimental/';
const DEPENDENCIES_DIRECTORY = 'dependencies';
function initDependencies() {
@ -39,7 +39,7 @@ function initServer() {
const host = 'localhost';
const port = 8000;
const requestListener = function(request, response) {
const requestListener = function (request, response) {
let contents;
switch (request.url) {
case '/react.js':

View File

@ -334,6 +334,11 @@
},
});
class Foo {
flag = false;
object = {a: {b: {c: {d: 1}}}}
}
function UnserializableProps() {
return (
<ChildComponent
@ -343,6 +348,7 @@
setOfSets={setOfSets}
typedArray={typedArray}
immutable={immutable}
classInstance={new Foo()}
/>
);
}

View File

@ -11,7 +11,7 @@
"classnames": "^2.2.5",
"codemirror": "^5.40.0",
"core-js": "^2.4.1",
"jest-diff": "^25.1.0",
"jest-diff": "^29.4.1",
"prop-types": "^15.6.0",
"query-string": "^4.2.3",
"react": "^15.4.1",
@ -19,8 +19,8 @@
"semver": "^5.5.0"
},
"scripts": {
"start": "react-scripts start",
"prestart": "cp ../../build/oss-stable/scheduler/umd/scheduler-unstable_mock.development.js ../../build/oss-stable/scheduler/umd/scheduler-unstable_mock.production.min.js ../../build/oss-stable/react/umd/react.development.js ../../build/oss-stable/react-dom/umd/react-dom.development.js ../../build/oss-stable/react/umd/react.production.min.js ../../build/oss-stable/react-dom/umd/react-dom.production.min.js ../../build/oss-stable/react-dom/umd/react-dom-server.browser.development.js ../../build/oss-stable/react-dom/umd/react-dom-server.browser.production.min.js ../../build/oss-stable/react-dom/umd/react-dom-test-utils.development.js ../../build/oss-stable/react-dom/umd/react-dom-test-utils.production.min.js public/ && cp -a ../../build/oss-stable/. node_modules",
"dev": "react-scripts start",
"predev": "cp ../../build/oss-stable/scheduler/umd/scheduler-unstable_mock.development.js ../../build/oss-stable/scheduler/umd/scheduler-unstable_mock.production.min.js ../../build/oss-stable/react/umd/react.development.js ../../build/oss-stable/react-dom/umd/react-dom.development.js ../../build/oss-stable/react/umd/react.production.min.js ../../build/oss-stable/react-dom/umd/react-dom.production.min.js ../../build/oss-stable/react-dom/umd/react-dom-server.browser.development.js ../../build/oss-stable/react-dom/umd/react-dom-server.browser.production.min.js ../../build/oss-stable/react-dom/umd/react-dom-test-utils.development.js ../../build/oss-stable/react-dom/umd/react-dom-test-utils.production.min.js public/ && cp -a ../../build/oss-stable/. node_modules",
"build": "react-scripts build && cp build/index.html build/200.html",
"test": "react-scripts test --env=jsdom",
"eject": "react-scripts eject"

View File

@ -4,7 +4,7 @@
'use strict';
(function() {
(function () {
var Fixture = null;
var output = document.getElementById('output');
var status = document.getElementById('status');
@ -60,7 +60,7 @@
setStatus('Generating markup');
return Promise.resolve()
.then(function() {
.then(function () {
const element = createElement(Fixture);
// Server rendering moved to a separate package along with ReactDOM
@ -80,11 +80,11 @@
}
// Finally, React 0.4 and lower emits markup in a callback
return new Promise(function(resolve) {
return new Promise(function (resolve) {
React.renderComponentToString(element, resolve);
});
})
.then(function(string) {
.then(function (string) {
output.innerHTML = string;
setStatus('Markup only (No React)');
})
@ -124,13 +124,13 @@
}
function loadScript(src) {
return new Promise(function(resolve, reject) {
return new Promise(function (resolve, reject) {
var script = document.createElement('script');
script.async = true;
script.src = src;
script.onload = resolve;
script.onerror = function(error) {
script.onerror = function (error) {
reject(new Error('Unable to load ' + src));
};
@ -145,7 +145,7 @@
setStatus('Failed');
output.innerHTML = 'Please name your root component "Fixture"';
} else {
prerender().then(function() {
prerender().then(function () {
if (getBooleanQueryParam('hydrate')) {
render();
}
@ -161,14 +161,14 @@
window.onerror = handleError;
reload.onclick = function() {
reload.onclick = function () {
window.location.reload();
};
hydrate.onclick = render;
loadScript(getQueryParam('reactPath'))
.then(function() {
.then(function () {
if (needsReactDOM) {
return Promise.all([
loadScript(getQueryParam('reactDOMPath')),
@ -176,12 +176,12 @@
]);
}
})
.then(function() {
.then(function () {
if (failed) {
return;
}
window.addEventListener('message', function(event) {
window.addEventListener('message', function (event) {
var data = JSON.parse(event.data);
switch (data.type) {

View File

@ -243,7 +243,7 @@ class TrySilenceFatalError extends React.Component {
function naiveMemoize(fn) {
let memoizedEntry;
return function() {
return function () {
if (!memoizedEntry) {
memoizedEntry = {result: null};
memoizedEntry.result = fn();
@ -251,7 +251,7 @@ function naiveMemoize(fn) {
return memoizedEntry.result;
};
}
let memoizedFunction = naiveMemoize(function() {
let memoizedFunction = naiveMemoize(function () {
throw new Error('Passed');
});

View File

@ -34,7 +34,7 @@ export class CodeEditor extends React.Component {
lineNumbers: true,
});
this.editor.on('change', function(doc) {
this.editor.on('change', function (doc) {
onChange(doc.getValue());
});
}

View File

@ -6,7 +6,7 @@ const ReactDOM = window.ReactDOM;
const MouseEnter = () => {
const containerRef = React.useRef();
React.useEffect(function() {
React.useEffect(function () {
const hostEl = containerRef.current;
ReactDOM.render(<MouseEnterDetect />, hostEl, () => {
ReactDOM.render(<MouseEnterDetect />, hostEl.childNodes[1]);

View File

@ -8,7 +8,7 @@ import 'core-js/es6/map';
// requestAnimationFrame polyfill by Erik Möller. fixes from Paul Irish and Tino Zijdel
// MIT license
(function() {
(function () {
var lastTime = 0;
var vendors = ['ms', 'moz', 'webkit', 'o'];
for (var x = 0; x < vendors.length && !window.requestAnimationFrame; ++x) {
@ -19,10 +19,10 @@ import 'core-js/es6/map';
}
if (!window.requestAnimationFrame)
window.requestAnimationFrame = function(callback, element) {
window.requestAnimationFrame = function (callback, element) {
var currTime = new Date().getTime();
var timeToCall = Math.max(0, 16 - (currTime - lastTime));
var id = window.setTimeout(function() {
var id = window.setTimeout(function () {
callback(currTime + timeToCall);
}, timeToCall);
lastTime = currTime + timeToCall;
@ -30,7 +30,7 @@ import 'core-js/es6/map';
};
if (!window.cancelAnimationFrame)
window.cancelAnimationFrame = function(id) {
window.cancelAnimationFrame = function (id) {
clearTimeout(id);
};
})();

View File

@ -11,7 +11,7 @@ import semver from 'semver';
function parseQuery(qstr) {
var query = {};
var a = qstr.substr(1).split('&');
var a = qstr.slice(1).split('&');
for (var i = 0; i < a.length; i++) {
var b = a[i].split('=');

View File

@ -1,7 +1,7 @@
// copied from scripts/jest/matchers/toWarnDev.js
'use strict';
const jestDiff = require('jest-diff').default;
const {diff: jestDiff} = require('jest-diff');
const util = require('util');
function shouldIgnoreConsoleError(format, args) {

View File

@ -7,47 +7,17 @@
resolved "https://registry.yarnpkg.com/@babel/standalone/-/standalone-7.12.10.tgz#f77f6750d0ab88c7c23234dd2d2f3800f170a573"
integrity sha512-e3sJ7uwwjiGWv7qeATKrP+Mjltr6JEurPh3yR0dBb9ie2YDnKl52lO82f+Ha+HAtyxTHfsPIXwgFmWKsCT2zOQ==
"@jest/types@^25.5.0":
version "25.5.0"
resolved "https://registry.yarnpkg.com/@jest/types/-/types-25.5.0.tgz#4d6a4793f7b9599fc3680877b856a97dbccf2a9d"
integrity sha512-OXD0RgQ86Tu3MazKo8bnrkDRaDXXMGUqd+kTtLtK1Zb7CRzQcaSRPPPV37SvYTdevXEBVxe0HXylEjs8ibkmCw==
"@jest/schemas@^29.4.0":
version "29.4.0"
resolved "https://registry.yarnpkg.com/@jest/schemas/-/schemas-29.4.0.tgz#0d6ad358f295cc1deca0b643e6b4c86ebd539f17"
integrity sha512-0E01f/gOZeNTG76i5eWWSupvSHaIINrTie7vCyjiYFKgzNdyEGd12BUv4oNBFHOqlHDbtoJi3HrQ38KCC90NsQ==
dependencies:
"@types/istanbul-lib-coverage" "^2.0.0"
"@types/istanbul-reports" "^1.1.1"
"@types/yargs" "^15.0.0"
chalk "^3.0.0"
"@sinclair/typebox" "^0.25.16"
"@types/istanbul-lib-coverage@*", "@types/istanbul-lib-coverage@^2.0.0":
version "2.0.3"
resolved "https://registry.yarnpkg.com/@types/istanbul-lib-coverage/-/istanbul-lib-coverage-2.0.3.tgz#4ba8ddb720221f432e443bd5f9117fd22cfd4762"
integrity sha512-sz7iLqvVUg1gIedBOvlkxPlc8/uVzyS5OwGz1cKjXzkl3FpL3al0crU8YGU1WoHkxn0Wxbw5tyi6hvzJKNzFsw==
"@types/istanbul-lib-report@*":
version "3.0.0"
resolved "https://registry.yarnpkg.com/@types/istanbul-lib-report/-/istanbul-lib-report-3.0.0.tgz#c14c24f18ea8190c118ee7562b7ff99a36552686"
integrity sha512-plGgXAPfVKFoYfa9NpYDAkseG+g6Jr294RqeqcqDixSbU34MZVJRi/P+7Y8GDpzkEwLaGZZOpKIEmeVZNtKsrg==
dependencies:
"@types/istanbul-lib-coverage" "*"
"@types/istanbul-reports@^1.1.1":
version "1.1.2"
resolved "https://registry.yarnpkg.com/@types/istanbul-reports/-/istanbul-reports-1.1.2.tgz#e875cc689e47bce549ec81f3df5e6f6f11cfaeb2"
integrity sha512-P/W9yOX/3oPZSpaYOCQzGqgCQRXn0FFO/V8bWrCQs+wLmvVVxk6CRBXALEvNs9OHIatlnlFokfhuDo2ug01ciw==
dependencies:
"@types/istanbul-lib-coverage" "*"
"@types/istanbul-lib-report" "*"
"@types/yargs-parser@*":
version "15.0.0"
resolved "https://registry.yarnpkg.com/@types/yargs-parser/-/yargs-parser-15.0.0.tgz#cb3f9f741869e20cce330ffbeb9271590483882d"
integrity sha512-FA/BWv8t8ZWJ+gEOnLLd8ygxH/2UFbAvgEonyfN6yWGLKc7zVjbpl2Y4CTjid9h2RfgPP6SEt6uHwEOply00yw==
"@types/yargs@^15.0.0":
version "15.0.11"
resolved "https://registry.yarnpkg.com/@types/yargs/-/yargs-15.0.11.tgz#361d7579ecdac1527687bcebf9946621c12ab78c"
integrity sha512-jfcNBxHFYJ4nPIacsi3woz1+kvUO6s1CyeEhtnDHBjHUMNj5UlW2GynmnSgiJJEdNg9yW5C8lfoNRZrHGv5EqA==
dependencies:
"@types/yargs-parser" "*"
"@sinclair/typebox@^0.25.16":
version "0.25.21"
resolved "https://registry.yarnpkg.com/@sinclair/typebox/-/typebox-0.25.21.tgz#763b05a4b472c93a8db29b2c3e359d55b29ce272"
integrity sha512-gFukHN4t8K4+wVC+ECqeqwzBDeFeTzBXroBTqE6vcWrQGbEUpHO7LYdG0f4xnvYq4VOEwITSlHlp0JBAIFMS/g==
abab@^1.0.3:
version "1.0.4"
@ -184,11 +154,6 @@ ansi-regex@^3.0.0:
resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-3.0.0.tgz#ed0317c322064f79466c02966bddb605ab37d998"
integrity sha1-7QMXwyIGT3lGbAKWa922Bas32Zg=
ansi-regex@^5.0.0:
version "5.0.0"
resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-5.0.0.tgz#388539f55179bf39339c81af30a654d69f87cb75"
integrity sha512-bY6fj56OUQ0hU1KjFNDQuJFezqKdrAyFdIevADiqrWHwSlbmBNMHp5ak2f40Pm8JTFyM2mqxkG6ngkHO11f/lg==
ansi-styles@^2.2.1:
version "2.2.1"
resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-2.2.1.tgz#b432dd3358b634cf75e1e4664368240533c1ddbe"
@ -201,13 +166,18 @@ ansi-styles@^3.0.0, ansi-styles@^3.2.1:
dependencies:
color-convert "^1.9.0"
ansi-styles@^4.0.0, ansi-styles@^4.1.0:
ansi-styles@^4.1.0:
version "4.3.0"
resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-4.3.0.tgz#edd803628ae71c04c85ae7a0906edad34b648937"
integrity sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==
dependencies:
color-convert "^2.0.1"
ansi-styles@^5.0.0:
version "5.2.0"
resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-5.2.0.tgz#07449690ad45777d1924ac2abb2fc8895dba836b"
integrity sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==
anymatch@^1.3.0:
version "1.3.2"
resolved "https://registry.yarnpkg.com/anymatch/-/anymatch-1.3.2.tgz#553dcb8f91e3c889845dfdba34c77721b90b9d7a"
@ -1655,10 +1625,10 @@ chalk@^2.0.0, chalk@^2.0.1, chalk@^2.1.0, chalk@^2.4.1:
escape-string-regexp "^1.0.5"
supports-color "^5.3.0"
chalk@^3.0.0:
version "3.0.0"
resolved "https://registry.yarnpkg.com/chalk/-/chalk-3.0.0.tgz#3f73c2bf526591f574cc492c51e2456349f844e4"
integrity sha512-4D3B6Wf41KOYRFdszmDqMCGq5VV/uMAB273JILmO+3jAlh8X4qDtdtgCR3fxtbLEMzSx22QdhnDcJvu2u1fVwg==
chalk@^4.0.0:
version "4.1.2"
resolved "https://registry.yarnpkg.com/chalk/-/chalk-4.1.2.tgz#aac4e2b7734a740867aeb16bf02aad556a1e7a01"
integrity sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==
dependencies:
ansi-styles "^4.1.0"
supports-color "^7.1.0"
@ -2409,10 +2379,10 @@ detect-port-alt@1.1.6:
address "^1.0.1"
debug "^2.6.0"
diff-sequences@^25.2.6:
version "25.2.6"
resolved "https://registry.yarnpkg.com/diff-sequences/-/diff-sequences-25.2.6.tgz#5f467c00edd35352b7bca46d7927d60e687a76dd"
integrity sha512-Hq8o7+6GaZeoFjtpgvRBUknSXNeJiCx7V9Fr94ZMljNiCr9n9L8H8aJqgWOQiDDGdyn29fRNcDdRVJ5fdyihfg==
diff-sequences@^29.3.1:
version "29.3.1"
resolved "https://registry.yarnpkg.com/diff-sequences/-/diff-sequences-29.3.1.tgz#104b5b95fe725932421a9c6e5b4bef84c3f2249e"
integrity sha512-hlM3QR272NXCi4pq+N4Kok4kOp6EsgOM3ZSpJI7Da3UAs+Ttsi8MRmB6trM/lhyzUxGfOgnpkHtgqm5Q/CTcfQ==
diff@^3.2.0:
version "3.5.0"
@ -4599,15 +4569,15 @@ jest-diff@^20.0.3:
jest-matcher-utils "^20.0.3"
pretty-format "^20.0.3"
jest-diff@^25.1.0:
version "25.5.0"
resolved "https://registry.yarnpkg.com/jest-diff/-/jest-diff-25.5.0.tgz#1dd26ed64f96667c068cef026b677dfa01afcfa9"
integrity sha512-z1kygetuPiREYdNIumRpAHY6RXiGmp70YHptjdaxTWGmA085W3iCnXNx0DhflK3vwrKmrRWyY1wUpkPMVxMK7A==
jest-diff@^29.4.1:
version "29.4.1"
resolved "https://registry.yarnpkg.com/jest-diff/-/jest-diff-29.4.1.tgz#9a6dc715037e1fa7a8a44554e7d272088c4029bd"
integrity sha512-uazdl2g331iY56CEyfbNA0Ut7Mn2ulAG5vUaEHXycf1L6IPyuImIxSz4F0VYBKi7LYIuxOwTZzK3wh5jHzASMw==
dependencies:
chalk "^3.0.0"
diff-sequences "^25.2.6"
jest-get-type "^25.2.6"
pretty-format "^25.5.0"
chalk "^4.0.0"
diff-sequences "^29.3.1"
jest-get-type "^29.2.0"
pretty-format "^29.4.1"
jest-docblock@^20.0.3:
version "20.0.3"
@ -4631,10 +4601,10 @@ jest-environment-node@^20.0.3:
jest-mock "^20.0.3"
jest-util "^20.0.3"
jest-get-type@^25.2.6:
version "25.2.6"
resolved "https://registry.yarnpkg.com/jest-get-type/-/jest-get-type-25.2.6.tgz#0b0a32fab8908b44d508be81681487dbabb8d877"
integrity sha512-DxjtyzOHjObRM+sM1knti6or+eOgcGU4xVSb2HNP1TqO4ahsT+rqZg+nyqHWJSvWgKC5cG3QjGFBqxLghiF/Ig==
jest-get-type@^29.2.0:
version "29.2.0"
resolved "https://registry.yarnpkg.com/jest-get-type/-/jest-get-type-29.2.0.tgz#726646f927ef61d583a3b3adb1ab13f3a5036408"
integrity sha512-uXNJlg8hKFEnDgFsrCjznB+sTxdkuqiCL6zMgA75qEbAJjJYTs9XPrvDctrEig2GDow22T/LvHgO57iJhXB/UA==
jest-haste-map@^20.0.4:
version "20.0.5"
@ -6359,15 +6329,14 @@ pretty-format@^20.0.3:
ansi-regex "^2.1.1"
ansi-styles "^3.0.0"
pretty-format@^25.5.0:
version "25.5.0"
resolved "https://registry.yarnpkg.com/pretty-format/-/pretty-format-25.5.0.tgz#7873c1d774f682c34b8d48b6743a2bf2ac55791a"
integrity sha512-kbo/kq2LQ/A/is0PQwsEHM7Ca6//bGPPvU6UnsdDRSKTWxT/ru/xb88v4BJf6a69H+uTytOEsTusT9ksd/1iWQ==
pretty-format@^29.4.1:
version "29.4.1"
resolved "https://registry.yarnpkg.com/pretty-format/-/pretty-format-29.4.1.tgz#0da99b532559097b8254298da7c75a0785b1751c"
integrity sha512-dt/Z761JUVsrIKaY215o1xQJBGlSmTx/h4cSqXqjHLnU1+Kt+mavVE7UgqJJO5ukx5HjSswHfmXz4LjS2oIJfg==
dependencies:
"@jest/types" "^25.5.0"
ansi-regex "^5.0.0"
ansi-styles "^4.0.0"
react-is "^16.12.0"
"@jest/schemas" "^29.4.0"
ansi-styles "^5.0.0"
react-is "^18.0.0"
private@^0.1.6, private@^0.1.7, private@^0.1.8:
version "0.1.8"
@ -6595,11 +6564,16 @@ react-error-overlay@^4.0.1:
resolved "https://registry.yarnpkg.com/react-error-overlay/-/react-error-overlay-4.0.1.tgz#417addb0814a90f3a7082eacba7cee588d00da89"
integrity sha512-xXUbDAZkU08aAkjtUvldqbvI04ogv+a1XdHxvYuHPYKIVk/42BIOD0zSKTHAWV4+gDy3yGm283z2072rA2gdtw==
react-is@^16.12.0, react-is@^16.8.1:
react-is@^16.8.1:
version "16.13.1"
resolved "https://registry.yarnpkg.com/react-is/-/react-is-16.13.1.tgz#789729a4dc36de2999dc156dd6c1d9c18cea56a4"
integrity sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==
react-is@^18.0.0:
version "18.2.0"
resolved "https://registry.yarnpkg.com/react-is/-/react-is-18.2.0.tgz#199431eeaaa2e09f86427efbb4f1473edb47609b"
integrity sha512-xWGDIW6x921xtzPkhiULtthJHoJvBbF3q26fzloPCK0hsvxtPVelvftw3zjbHWSkR2km9Z+4uxbDDK/6Zw9B8w==
react-scripts@^1.0.11:
version "1.1.5"
resolved "https://registry.yarnpkg.com/react-scripts/-/react-scripts-1.1.5.tgz#3041610ab0826736b52197711a4c4e3756e97768"

View File

@ -16,7 +16,7 @@ function reload() {
}
}
// Point to the built version.
build = require('../../../build/node_modules/eslint-plugin-react-hooks');
build = require('../../../build/oss-experimental/eslint-plugin-react-hooks');
}
let rules = {};

View File

@ -8,9 +8,9 @@
"react-scripts": "1.0.17"
},
"scripts": {
"prestart":
"cp ../../build/node_modules/react/umd/react.development.js public/ && cp ../../build/node_modules/react-dom/umd/react-dom.development.js public/",
"start": "react-scripts start",
"predev":
"cp ../../build/oss-experimental/react/umd/react.development.js public/ && cp ../../build/oss-experimental/react-dom/umd/react-dom.development.js public/",
"dev": "react-scripts start",
"build": "react-scripts build",
"test": "react-scripts test --env=jsdom",
"eject": "react-scripts eject"

View File

@ -12,7 +12,7 @@
"react-motion": "^0.5.0"
},
"scripts": {
"start": "react-scripts start",
"dev": "react-scripts start",
"build": "react-scripts build"
}
}

View File

@ -29,7 +29,7 @@ function Graph(props) {
});
var edgeLabels = {};
React.Children.forEach(props.children, function(child) {
React.Children.forEach(props.children, function (child) {
if (!child) {
return;
}

View File

@ -16,8 +16,8 @@
If you checked out the source from GitHub make sure to run <code>npm run build</code>.
</p>
</div>
<script src="../../build/node_modules/react/umd/react.development.js"></script>
<script src="../../build/node_modules/react-dom/umd/react-dom.development.js"></script>
<script src="../../build/oss-experimental/react/umd/react.development.js"></script>
<script src="../../build/oss-experimental/react-dom/umd/react-dom.development.js"></script>
<script src="https://unpkg.com/babel-standalone@6/babel.js"></script>
<script type="text/babel">
var dotStyle = {

View File

@ -16,9 +16,9 @@
If you checked out the source from GitHub make sure to run <code>npm run build</code>.
</p>
</div>
<script src="../../build/node_modules/react/umd/react.development.js"></script>
<script src="../../build/node_modules/react-dom/umd/react-dom.development.js"></script>
<script src="../../build/node_modules/react-dom/umd/react-dom-server.browser.development.js"></script>
<script src="../../build/oss-experimental/react/umd/react.development.js"></script>
<script src="../../build/oss-experimental/react-dom/umd/react-dom.development.js"></script>
<script src="../../build/oss-experimental/react-dom/umd/react-dom-server.browser.development.js"></script>
<script src="https://unpkg.com/babel-standalone@6/babel.js"></script>
<script type="text/babel">
async function render() {

View File

@ -15,8 +15,8 @@
"concurrently": "^5.3.0",
"express": "^4.17.1",
"nodemon": "^2.0.6",
"react": "link:../../build/node_modules/react",
"react-dom": "link:../../build/node_modules/react-dom",
"react": "^18.2.0",
"react-dom": "^18.2.0",
"react-error-boundary": "^3.1.3",
"resolve": "1.12.0",
"rimraf": "^3.0.2",
@ -28,12 +28,14 @@
"prettier": "1.19.1"
},
"scripts": {
"start": "concurrently \"npm run server:dev\" \"npm run bundler:dev\"",
"start:prod": "concurrently \"npm run server:prod\" \"npm run bundler:prod\"",
"server:dev": "cross-env NODE_ENV=development nodemon -- --inspect server/server.js",
"server:prod": "cross-env NODE_ENV=production nodemon -- server/server.js",
"bundler:dev": "cross-env NODE_ENV=development nodemon -- scripts/build.js",
"bundler:prod": "cross-env NODE_ENV=production nodemon -- scripts/build.js"
"predev": "cp -r ../../build/oss-experimental/* ./node_modules/",
"prestart": "cp -r ../../build/oss-experimental/* ./node_modules/",
"dev": "concurrently \"npm run dev:server\" \"npm run dev:bundler\"",
"start": "concurrently \"npm run start:server\" \"npm run start:bundler\"",
"dev:server": "cross-env NODE_ENV=development nodemon -- --inspect server/server.js",
"start:server": "cross-env NODE_ENV=production nodemon -- server/server.js",
"dev:bundler": "cross-env NODE_ENV=development nodemon -- scripts/build.js",
"start:bundler": "cross-env NODE_ENV=production nodemon -- scripts/build.js"
},
"babel": {
"presets": [

View File

@ -30,28 +30,28 @@ const app = express();
app.use(compress());
app.get(
'/',
handleErrors(async function(req, res) {
handleErrors(async function (req, res) {
await waitForWebpack();
renderToStream(req.url, res);
})
);
app.get(
'/string',
handleErrors(async function(req, res) {
handleErrors(async function (req, res) {
await waitForWebpack();
renderToString(req.url, res);
})
);
app.get(
'/stream',
handleErrors(async function(req, res) {
handleErrors(async function (req, res) {
await waitForWebpack();
renderToStream(req.url, res);
})
);
app.get(
'/buffer',
handleErrors(async function(req, res) {
handleErrors(async function (req, res) {
await waitForWebpack();
renderToBuffer(req.url, res);
})
@ -63,7 +63,7 @@ app
.listen(PORT, () => {
console.log(`Listening at ${PORT}...`);
})
.on('error', function(error) {
.on('error', function (error) {
if (error.syscall !== 'listen') {
throw error;
}
@ -84,7 +84,7 @@ app
});
function handleErrors(fn) {
return async function(req, res, next) {
return async function (req, res, next) {
try {
return await fn(req, res);
} catch (x) {

View File

@ -3171,7 +3171,7 @@ isobject@^3.0.0, isobject@^3.0.1:
resolved "https://registry.yarnpkg.com/isobject/-/isobject-3.0.1.tgz#4e431e92b11a9731636aa1f9c8d1ccbcfdab78df"
integrity sha1-TkMekrEalzFjaqH5yNHMvP2reN8=
js-tokens@^4.0.0:
"js-tokens@^3.0.0 || ^4.0.0", js-tokens@^4.0.0:
version "4.0.0"
resolved "https://registry.yarnpkg.com/js-tokens/-/js-tokens-4.0.0.tgz#19203fb59991df98e3a287050d4647cdeaf32499"
integrity sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==
@ -3295,6 +3295,13 @@ lodash@^4.17.15, lodash@^4.17.19:
resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.21.tgz#679591c564c3bffaae8454cf0b3df370c3d6911c"
integrity sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==
loose-envify@^1.1.0:
version "1.4.0"
resolved "https://registry.yarnpkg.com/loose-envify/-/loose-envify-1.4.0.tgz#71ee51fa7be4caec1a63839f7e682d8132d30caf"
integrity sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q==
dependencies:
js-tokens "^3.0.0 || ^4.0.0"
lowercase-keys@^1.0.0, lowercase-keys@^1.0.1:
version "1.0.1"
resolved "https://registry.yarnpkg.com/lowercase-keys/-/lowercase-keys-1.0.1.tgz#6f9e30b47084d971a7c820ff15a6c5167b74c26f"
@ -4083,8 +4090,13 @@ rc@^1.2.8:
minimist "^1.2.0"
strip-json-comments "~2.0.1"
"react-dom@link:../../build/node_modules/react-dom":
version "0.0.0"
react-dom@^18.2.0:
version "18.2.0"
resolved "https://registry.yarnpkg.com/react-dom/-/react-dom-18.2.0.tgz#22aaf38708db2674ed9ada224ca4aa708d821e3d"
integrity sha512-6IMTriUmvsjHUjNtEDudZfuDQUoWXVxKHhlEGSk81n4YFS+r/Kl99wXiwlVXtPBtJenozv2P+hxDsw9eA7Xo6g==
dependencies:
loose-envify "^1.1.0"
scheduler "^0.23.0"
react-error-boundary@^3.1.3:
version "3.1.4"
@ -4093,8 +4105,12 @@ react-error-boundary@^3.1.3:
dependencies:
"@babel/runtime" "^7.12.5"
"react@link:../../build/node_modules/react":
version "0.0.0"
react@^18.2.0:
version "18.2.0"
resolved "https://registry.yarnpkg.com/react/-/react-18.2.0.tgz#555bd98592883255fa00de14f1151a917b5d77d5"
integrity sha512-/3IjMdb2L9QbBdWiW5e3P2/npwMBaU9mHCSCUzNln0ZCYbcfTsGbTJrU/kGemdH2IWmB2ioZ+zkxtmq6g09fGQ==
dependencies:
loose-envify "^1.1.0"
read-pkg@^4.0.1:
version "4.0.1"
@ -4353,6 +4369,13 @@ safe-regex@^1.1.0:
resolved "https://registry.yarnpkg.com/safer-buffer/-/safer-buffer-2.1.2.tgz#44fa161b0187b9549dd84bb91802f9bd8385cd6a"
integrity sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==
scheduler@^0.23.0:
version "0.23.0"
resolved "https://registry.yarnpkg.com/scheduler/-/scheduler-0.23.0.tgz#ba8041afc3d30eb206a487b6b384002e4e61fdfe"
integrity sha512-CtuThmgHNg7zIZWAXi3AsyIzA3n4xx7aNyjwC2VJldO2LMVDhFK+63xGqq6CsJH4rTAt6/M+N4GhZiDYPx9eUw==
dependencies:
loose-envify "^1.1.0"
schema-utils@^1.0.0:
version "1.0.0"
resolved "https://registry.yarnpkg.com/schema-utils/-/schema-utils-1.0.0.tgz#0b79a93204d7b600d4b2850d1f66c2a34951c770"

View File

@ -16,11 +16,11 @@
If you checked out the source from GitHub make sure to run <code>npm run build</code>.
</p>
</div>
<script src="../../build/node_modules/react/umd/react.development.js"></script>
<script src="../../build/node_modules/react-dom/umd/react-dom.development.js"></script>
<script src="../../build/node_modules/react-dom/umd/react-dom-server.browser.development.js"></script>
<script src="../../build/node_modules/react-server-dom-webpack/umd/react-server-dom-webpack-server.browser.development.js"></script>
<script src="../../build/node_modules/react-server-dom-webpack/umd/react-server-dom-webpack.development.js"></script>
<script src="../../build/oss-experimental/react/umd/react.development.js"></script>
<script src="../../build/oss-experimental/react-dom/umd/react-dom.development.js"></script>
<script src="../../build/oss-experimental/react-dom/umd/react-dom-server.browser.development.js"></script>
<script src="../../build/oss-experimental/react-server-dom-webpack/umd/react-server-dom-webpack-server.browser.development.js"></script>
<script src="../../build/oss-experimental/react-server-dom-webpack/umd/react-server-dom-webpack-client.browser.development.js"></script>
<script src="https://unpkg.com/babel-standalone@6/babel.js"></script>
<script type="text/babel">
let Suspense = React.Suspense;
@ -60,7 +60,7 @@
content: <HTML />,
};
let stream = ReactServerDOMWriter.renderToReadableStream(model);
let stream = ReactServerDOMServer.renderToReadableStream(model);
let response = new Response(stream, {
headers: {'Content-Type': 'text/html'},
});
@ -70,13 +70,13 @@
let blob = await responseToDisplay.blob();
let url = URL.createObjectURL(blob);
let data = ReactServerDOMReader.createFromFetch(
let data = ReactServerDOMClient.createFromFetch(
fetch(url)
);
// The client also supports XHR streaming.
// var xhr = new XMLHttpRequest();
// xhr.open('GET', url);
// let data = ReactServerDOMReader.createFromXHR(xhr);
// let data = ReactServerDOMClient.createFromXHR(xhr);
// xhr.send();
renderResult(data);

View File

@ -10,7 +10,6 @@
# production
/build
/dist
.eslintcache
# misc

View File

@ -1,66 +0,0 @@
'use strict';
const fs = require('fs');
const path = require('path');
const crypto = require('crypto');
const chalk = require('react-dev-utils/chalk');
const paths = require('./paths');
// Ensure the certificate and key provided are valid and if not
// throw an easy to debug error
function validateKeyAndCerts({cert, key, keyFile, crtFile}) {
let encrypted;
try {
// publicEncrypt will throw an error with an invalid cert
encrypted = crypto.publicEncrypt(cert, Buffer.from('test'));
} catch (err) {
throw new Error(
`The certificate "${chalk.yellow(crtFile)}" is invalid.\n${err.message}`
);
}
try {
// privateDecrypt will throw an error with an invalid key
crypto.privateDecrypt(key, encrypted);
} catch (err) {
throw new Error(
`The certificate key "${chalk.yellow(keyFile)}" is invalid.\n${
err.message
}`
);
}
}
// Read file and throw an error if it doesn't exist
function readEnvFile(file, type) {
if (!fs.existsSync(file)) {
throw new Error(
`You specified ${chalk.cyan(
type
)} in your env, but the file "${chalk.yellow(file)}" can't be found.`
);
}
return fs.readFileSync(file);
}
// Get the https config
// Return cert files if provided in env, otherwise just true or false
function getHttpsConfig() {
const {SSL_CRT_FILE, SSL_KEY_FILE, HTTPS} = process.env;
const isHttps = HTTPS === 'true';
if (isHttps && SSL_CRT_FILE && SSL_KEY_FILE) {
const crtFile = path.resolve(paths.appPath, SSL_CRT_FILE);
const keyFile = path.resolve(paths.appPath, SSL_KEY_FILE);
const config = {
cert: readEnvFile(crtFile, 'SSL_CRT_FILE'),
key: readEnvFile(keyFile, 'SSL_KEY_FILE'),
};
validateKeyAndCerts({...config, keyFile, crtFile});
return config;
}
return isHttps;
}
module.exports = getHttpsConfig;

View File

@ -3,7 +3,7 @@
const fs = require('fs');
const path = require('path');
const paths = require('./paths');
const chalk = require('react-dev-utils/chalk');
const chalk = require('chalk');
const resolve = require('resolve');
/**

View File

@ -56,7 +56,6 @@ module.exports = {
appPath: resolveApp('.'),
appBuild: resolveApp(buildPath),
appPublic: resolveApp('public'),
appHtml: resolveApp('public/index.html'),
appIndexJs: resolveModule(resolveApp, 'src/index'),
appPackageJson: resolveApp('package.json'),
appSrc: resolveApp('src'),
@ -64,7 +63,6 @@ module.exports = {
appJsConfig: resolveApp('jsconfig.json'),
yarnLockFile: resolveApp('yarn.lock'),
testsSetup: resolveModule(resolveApp, 'src/setupTests'),
proxySetup: resolveApp('src/setupProxy.js'),
appNodeModules: resolveApp('node_modules'),
appWebpackCache: resolveApp('node_modules/.cache'),
appTsBuildInfoFile: resolveApp('node_modules/.cache/tsconfig.tsbuildinfo'),

View File

@ -5,18 +5,14 @@ const ReactFlightWebpackPlugin = require('react-server-dom-webpack/plugin');
// Fork End
const fs = require('fs');
const {createHash} = require('crypto');
const path = require('path');
const webpack = require('webpack');
const resolve = require('resolve');
const HtmlWebpackPlugin = require('html-webpack-plugin');
const CaseSensitivePathsPlugin = require('case-sensitive-paths-webpack-plugin');
const InlineChunkHtmlPlugin = require('react-dev-utils/InlineChunkHtmlPlugin');
const TerserPlugin = require('terser-webpack-plugin');
const MiniCssExtractPlugin = require('mini-css-extract-plugin');
const CssMinimizerPlugin = require('css-minimizer-webpack-plugin');
const {WebpackManifestPlugin} = require('webpack-manifest-plugin');
const InterpolateHtmlPlugin = require('react-dev-utils/InterpolateHtmlPlugin');
const WorkboxWebpackPlugin = require('workbox-webpack-plugin');
const ModuleScopePlugin = require('react-dev-utils/ModuleScopePlugin');
const getCSSModuleLocalIdent = require('react-dev-utils/getCSSModuleLocalIdent');
const ESLintPlugin = require('eslint-webpack-plugin');
@ -29,8 +25,14 @@ const ForkTsCheckerWebpackPlugin =
? require('react-dev-utils/ForkTsCheckerWarningWebpackPlugin')
: require('react-dev-utils/ForkTsCheckerWebpackPlugin');
const ReactRefreshWebpackPlugin = require('@pmmmwh/react-refresh-webpack-plugin');
const {WebpackManifestPlugin} = require('webpack-manifest-plugin');
const createEnvironmentHash = require('./webpack/persistentCache/createEnvironmentHash');
function createEnvironmentHash(env) {
const hash = createHash('md5');
hash.update(JSON.stringify(env));
return hash.digest('hex');
}
// Source maps are resource heavy and can cause out of memory issue for large source files.
const shouldUseSourceMap = process.env.GENERATE_SOURCEMAP !== 'false';
@ -91,7 +93,7 @@ const hasJsxRuntime = (() => {
// This is the production and development configuration.
// It is focused on developer experience, fast rebuilds, and a minimal bundle.
module.exports = function(webpackEnv) {
module.exports = function (webpackEnv) {
const isEnvDevelopment = webpackEnv === 'development';
const isEnvProduction = webpackEnv === 'production';
@ -112,7 +114,7 @@ module.exports = function(webpackEnv) {
const getStyleLoaders = (cssOptions, preProcessor) => {
const loaders = [
isEnvDevelopment && require.resolve('style-loader'),
isEnvProduction && {
{
loader: MiniCssExtractPlugin.loader,
// css is located in `static/css`, use '../../' to locate index.html folder
// in production `paths.publicUrlOrPath` can be a relative path
@ -204,7 +206,13 @@ module.exports = function(webpackEnv) {
: isEnvDevelopment && 'cheap-module-source-map',
// These are the "entry points" to our application.
// This means they will be the "root" imports that are included in JS bundle.
entry: paths.appIndexJs,
entry: isEnvProduction
? [paths.appIndexJs]
: [
paths.appIndexJs,
// HMR client
'webpack-hot-middleware/client?path=/__webpack_hmr&timeout=20000',
],
output: {
// The build folder.
path: paths.appBuild,
@ -567,44 +575,7 @@ module.exports = function(webpackEnv) {
].filter(Boolean),
},
plugins: [
// Generates an `index.html` file with the <script> injected.
new HtmlWebpackPlugin(
Object.assign(
{},
{
inject: true,
template: paths.appHtml,
},
isEnvProduction
? {
minify: {
removeComments: true,
collapseWhitespace: true,
removeRedundantAttributes: true,
useShortDoctype: true,
removeEmptyAttributes: true,
removeStyleLinkTypeAttributes: true,
keepClosingSlash: true,
minifyJS: true,
minifyCSS: true,
minifyURLs: true,
},
}
: undefined
)
),
// Inlines the webpack runtime script. This script is too small to warrant
// a network request.
// https://github.com/facebook/create-react-app/issues/5358
isEnvProduction &&
shouldInlineRuntimeChunk &&
new InlineChunkHtmlPlugin(HtmlWebpackPlugin, [/runtime-.+[.]js/]),
// Makes some environment variables available in index.html.
// The public URL is available as %PUBLIC_URL% in index.html, e.g.:
// <link rel="icon" href="%PUBLIC_URL%/favicon.ico">
// It will be an empty string unless you specify "homepage"
// in `package.json`, in which case it will be the pathname of that URL.
new InterpolateHtmlPlugin(HtmlWebpackPlugin, env.raw),
new webpack.HotModuleReplacementPlugin(),
// This gives some necessary context to module not found errors, such as
// the requesting resource.
new ModuleNotFoundPlugin(paths.appPath),
@ -625,35 +596,38 @@ module.exports = function(webpackEnv) {
// a plugin that prints an error when you attempt to do this.
// See https://github.com/facebook/create-react-app/issues/240
isEnvDevelopment && new CaseSensitivePathsPlugin(),
isEnvProduction &&
new MiniCssExtractPlugin({
// Options similar to the same options in webpackOptions.output
// both options are optional
filename: 'static/css/[name].[contenthash:8].css',
chunkFilename: 'static/css/[name].[contenthash:8].chunk.css',
}),
// Generate an asset manifest file with the following content:
// - "files" key: Mapping of all asset filenames to their corresponding
// output file so that tools can pick it up without having to parse
// `index.html`
// - "entrypoints" key: Array of files which are included in `index.html`,
// can be used to reconstruct the HTML if necessary
new MiniCssExtractPlugin({
// Options similar to the same options in webpackOptions.output
// both options are optional
filename: 'static/css/[name].[contenthash:8].css',
chunkFilename: 'static/css/[name].[contenthash:8].chunk.css',
}),
// Generate a manifest containing the required script / css for each entry.
new WebpackManifestPlugin({
fileName: 'asset-manifest.json',
fileName: 'entrypoint-manifest.json',
publicPath: paths.publicUrlOrPath,
generate: (seed, files, entrypoints) => {
const manifestFiles = files.reduce((manifest, file) => {
manifest[file.name] = file.path;
return manifest;
}, seed);
const entrypointFiles = entrypoints.main.filter(
fileName => !fileName.endsWith('.map')
);
return {
files: manifestFiles,
entrypoints: entrypointFiles,
};
const processedEntrypoints = {};
for (let key in entrypoints) {
processedEntrypoints[key] = {
js: entrypoints[key].filter(
filename =>
// Include JS assets but ignore hot updates because they're not
// safe to include as async script tags.
filename.endsWith('.js') &&
!filename.endsWith('.hot-update.js')
),
css: entrypoints[key].filter(filename =>
filename.endsWith('.css')
),
};
}
return processedEntrypoints;
},
}),
// Moment.js is an extremely popular library that bundles large locale files
@ -665,19 +639,6 @@ module.exports = function(webpackEnv) {
resourceRegExp: /^\.\/locale$/,
contextRegExp: /moment$/,
}),
// Generate a service worker script that will precache, and keep up to date,
// the HTML & assets that are part of the webpack build.
isEnvProduction &&
fs.existsSync(swSrc) &&
new WorkboxWebpackPlugin.InjectManifest({
swSrc,
dontCacheBustURLsMatching: /\.[0-9a-f]{8}\./,
exclude: [/\.map$/, /asset-manifest\.json$/, /LICENSE/],
// Bump up the default maximum size (2mb) that's precached,
// to make lazy-loading failure scenarios less likely.
// See https://github.com/cra-template/pwa/issues/13#issuecomment-722667270
maximumFileSizeToCacheInBytes: 5 * 1024 * 1024,
}),
// TypeScript type checking
useTypeScript &&
new ForkTsCheckerWebpackPlugin({
@ -752,7 +713,14 @@ module.exports = function(webpackEnv) {
// },
// }),
// Fork Start
new ReactFlightWebpackPlugin({isServer: false}),
new ReactFlightWebpackPlugin({
isServer: false,
clientReferences: {
directory: './src',
recursive: true,
include: /\.(js|ts|jsx|tsx)$/,
},
}),
// Fork End
].filter(Boolean),
// Turn off performance processing because we utilize

View File

@ -1,9 +0,0 @@
'use strict';
const {createHash} = require('crypto');
module.exports = env => {
const hash = createHash('md5');
hash.update(JSON.stringify(env));
return hash.digest('hex');
};

View File

@ -1,133 +0,0 @@
'use strict';
const fs = require('fs');
const evalSourceMapMiddleware = require('react-dev-utils/evalSourceMapMiddleware');
const noopServiceWorkerMiddleware = require('react-dev-utils/noopServiceWorkerMiddleware');
const ignoredFiles = require('react-dev-utils/ignoredFiles');
const redirectServedPath = require('react-dev-utils/redirectServedPathMiddleware');
const paths = require('./paths');
const getHttpsConfig = require('./getHttpsConfig');
const host = process.env.HOST || '0.0.0.0';
const sockHost = process.env.WDS_SOCKET_HOST;
const sockPath = process.env.WDS_SOCKET_PATH; // default: '/ws'
const sockPort = process.env.WDS_SOCKET_PORT;
module.exports = function(proxy, allowedHost) {
const disableFirewall =
!proxy || process.env.DANGEROUSLY_DISABLE_HOST_CHECK === 'true';
return {
// WebpackDevServer 2.4.3 introduced a security fix that prevents remote
// websites from potentially accessing local content through DNS rebinding:
// https://github.com/webpack/webpack-dev-server/issues/887
// https://medium.com/webpack/webpack-dev-server-middleware-security-issues-1489d950874a
// However, it made several existing use cases such as development in cloud
// environment or subdomains in development significantly more complicated:
// https://github.com/facebook/create-react-app/issues/2271
// https://github.com/facebook/create-react-app/issues/2233
// While we're investigating better solutions, for now we will take a
// compromise. Since our WDS configuration only serves files in the `public`
// folder we won't consider accessing them a vulnerability. However, if you
// use the `proxy` feature, it gets more dangerous because it can expose
// remote code execution vulnerabilities in backends like Django and Rails.
// So we will disable the host check normally, but enable it if you have
// specified the `proxy` setting. Finally, we let you override it if you
// really know what you're doing with a special environment variable.
// Note: ["localhost", ".localhost"] will support subdomains - but we might
// want to allow setting the allowedHosts manually for more complex setups
allowedHosts: disableFirewall ? 'all' : [allowedHost],
headers: {
'Access-Control-Allow-Origin': '*',
'Access-Control-Allow-Methods': '*',
'Access-Control-Allow-Headers': '*',
},
// Enable gzip compression of generated files.
compress: true,
static: {
// By default WebpackDevServer serves physical files from current directory
// in addition to all the virtual build products that it serves from memory.
// This is confusing because those files wont automatically be available in
// production build folder unless we copy them. However, copying the whole
// project directory is dangerous because we may expose sensitive files.
// Instead, we establish a convention that only files in `public` directory
// get served. Our build script will copy `public` into the `build` folder.
// In `index.html`, you can get URL of `public` folder with %PUBLIC_URL%:
// <link rel="icon" href="%PUBLIC_URL%/favicon.ico">
// In JavaScript code, you can access it with `process.env.PUBLIC_URL`.
// Note that we only recommend to use `public` folder as an escape hatch
// for files like `favicon.ico`, `manifest.json`, and libraries that are
// for some reason broken when imported through webpack. If you just want to
// use an image, put it in `src` and `import` it from JavaScript instead.
directory: paths.appPublic,
publicPath: [paths.publicUrlOrPath],
// By default files from `contentBase` will not trigger a page reload.
watch: {
// Reportedly, this avoids CPU overload on some systems.
// https://github.com/facebook/create-react-app/issues/293
// src/node_modules is not ignored to support absolute imports
// https://github.com/facebook/create-react-app/issues/1065
ignored: ignoredFiles(paths.appSrc),
},
},
client: {
webSocketURL: {
// Enable custom sockjs pathname for websocket connection to hot reloading server.
// Enable custom sockjs hostname, pathname and port for websocket connection
// to hot reloading server.
hostname: sockHost,
pathname: sockPath,
port: sockPort,
},
overlay: {
errors: true,
warnings: false,
},
},
devMiddleware: {
// Fork Start
writeToDisk: filePath => {
return /react-client-manifest\.json$/.test(filePath);
},
// Fork End
// It is important to tell WebpackDevServer to use the same "publicPath" path as
// we specified in the webpack config. When homepage is '.', default to serving
// from the root.
// remove last slash so user can land on `/test` instead of `/test/`
publicPath: paths.publicUrlOrPath.slice(0, -1),
},
https: getHttpsConfig(),
host,
historyApiFallback: {
// Paths with dots should still use the history fallback.
// See https://github.com/facebook/create-react-app/issues/387.
disableDotRule: true,
index: paths.publicUrlOrPath,
},
// `proxy` is run between `before` and `after` `webpack-dev-server` hooks
proxy,
onBeforeSetupMiddleware(devServer) {
// Keep `evalSourceMapMiddleware`
// middlewares before `redirectServedPath` otherwise will not have any effect
// This lets us fetch source contents from webpack for the error overlay
devServer.app.use(evalSourceMapMiddleware(devServer));
if (fs.existsSync(paths.proxySetup)) {
// This registers user provided middleware for proxy reasons
require(paths.proxySetup)(devServer.app);
}
},
onAfterSetupMiddleware(devServer) {
// Redirect to `PUBLIC_URL` or `homepage` from `package.json` if url not match
devServer.app.use(redirectServedPath(paths.publicUrlOrPath));
// This service worker file is effectively a 'no-op' that will reset any
// previous service worker registered for the same host:port combination.
// We do this in development to avoid hitting the production cache if
// it used the same host and port.
// https://github.com/facebook/create-react-app/issues/2272#issuecomment-302832432
devServer.app.use(noopServiceWorkerMiddleware(paths.publicUrlOrPath));
},
};
};

View File

@ -0,0 +1,51 @@
import babel from '@babel/core';
const babelOptions = {
babelrc: false,
ignore: [/\/(build|node_modules)\//],
plugins: [
'@babel/plugin-syntax-import-meta',
'@babel/plugin-transform-react-jsx',
],
};
export async function load(url, context, defaultLoad) {
const {format} = context;
const result = await defaultLoad(url, context, defaultLoad);
if (result.format === 'module') {
const opt = Object.assign({filename: url}, babelOptions);
const newResult = await babel.transformAsync(result.source, opt);
if (!newResult) {
if (typeof result.source === 'string') {
return result;
}
return {
source: Buffer.from(result.source).toString('utf8'),
format: 'module',
};
}
return {source: newResult.code, format: 'module'};
}
return defaultLoad(url, context, defaultLoad);
}
async function babelTransformSource(source, context, defaultTransformSource) {
const {format} = context;
if (format === 'module') {
const opt = Object.assign({filename: context.url}, babelOptions);
const newResult = await babel.transformAsync(source, opt);
if (!newResult) {
if (typeof source === 'string') {
return {source};
}
return {
source: Buffer.from(source).toString('utf8'),
};
}
return {source: newResult.code};
}
return defaultTransformSource(source, context, defaultTransformSource);
}
export const transformSource =
process.version < 'v16' ? babelTransformSource : undefined;

View File

@ -1,34 +0,0 @@
import {
resolve,
getSource,
transformSource as reactTransformSource,
} from 'react-server-dom-webpack/node-loader';
export {resolve, getSource};
import babel from '@babel/core';
const babelOptions = {
babelrc: false,
ignore: [/\/(build|node_modules)\//],
plugins: [
'@babel/plugin-syntax-import-meta',
'@babel/plugin-transform-react-jsx',
],
};
async function babelTransformSource(source, context, defaultTransformSource) {
const {format} = context;
if (format === 'module') {
const opt = Object.assign({filename: context.url}, babelOptions);
const {code} = await babel.transformAsync(source, opt);
return {source: code};
}
return defaultTransformSource(source, context, defaultTransformSource);
}
export async function transformSource(source, context, defaultTransformSource) {
return reactTransformSource(source, context, (s, c) => {
return babelTransformSource(s, c, defaultTransformSource);
});
}

View File

@ -0,0 +1,73 @@
import {
resolve,
load as reactLoad,
getSource as getSourceImpl,
transformSource as reactTransformSource,
} from 'react-server-dom-webpack/node-loader';
export {resolve};
import babel from '@babel/core';
const babelOptions = {
babelrc: false,
ignore: [/\/(build|node_modules)\//],
plugins: [
'@babel/plugin-syntax-import-meta',
'@babel/plugin-transform-react-jsx',
],
};
async function babelLoad(url, context, defaultLoad) {
const {format} = context;
const result = await defaultLoad(url, context, defaultLoad);
if (result.format === 'module') {
const opt = Object.assign({filename: url}, babelOptions);
const newResult = await babel.transformAsync(result.source, opt);
if (!newResult) {
if (typeof result.source === 'string') {
return result;
}
return {
source: Buffer.from(result.source).toString('utf8'),
format: 'module',
};
}
return {source: newResult.code, format: 'module'};
}
return defaultLoad(url, context, defaultLoad);
}
export async function load(url, context, defaultLoad) {
return await reactLoad(url, context, (u, c) => {
return babelLoad(u, c, defaultLoad);
});
}
async function babelTransformSource(source, context, defaultTransformSource) {
const {format} = context;
if (format === 'module') {
const opt = Object.assign({filename: context.url}, babelOptions);
const newResult = await babel.transformAsync(source, opt);
if (!newResult) {
if (typeof source === 'string') {
return {source};
}
return {
source: Buffer.from(source).toString('utf8'),
};
}
return {source: newResult.code};
}
return defaultTransformSource(source, context, defaultTransformSource);
}
async function transformSourceImpl(source, context, defaultTransformSource) {
return await reactTransformSource(source, context, (s, c) => {
return babelTransformSource(s, c, defaultTransformSource);
});
}
export const transformSource =
process.version < 'v16' ? transformSourceImpl : undefined;
export const getSource = process.version < 'v16' ? getSourceImpl : undefined;

View File

@ -15,10 +15,12 @@
"babel-loader": "^8.2.3",
"babel-plugin-named-asset-import": "^0.3.8",
"babel-preset-react-app": "^10.0.1",
"bfj": "^7.0.2",
"body-parser": "^1.20.1",
"browserslist": "^4.18.1",
"busboy": "^1.6.0",
"camelcase": "^6.2.1",
"case-sensitive-paths-webpack-plugin": "^2.4.0",
"compression": "^1.7.4",
"concurrently": "^7.3.0",
"css-loader": "^6.5.1",
"css-minimizer-webpack-plugin": "^3.2.0",
@ -42,10 +44,10 @@
"postcss-normalize": "^10.0.1",
"postcss-preset-env": "^7.0.1",
"prompts": "^2.4.2",
"react": "^18.2.0",
"react": "experimental",
"react-app-polyfill": "^3.0.0",
"react-dev-utils": "^12.0.1",
"react-dom": "^18.2.0",
"react-dom": "experimental",
"react-refresh": "^0.11.0",
"resolve": "^1.20.0",
"resolve-url-loader": "^4.0.0",
@ -55,21 +57,21 @@
"style-loader": "^3.3.1",
"tailwindcss": "^3.0.2",
"terser-webpack-plugin": "^5.2.5",
"web-vitals": "^2.1.0",
"undici": "^5.20.0",
"webpack": "^5.64.4",
"webpack-dev-server": "^4.6.0",
"webpack-manifest-plugin": "^4.0.2",
"workbox-webpack-plugin": "^6.4.1"
"webpack-dev-middleware": "^5.3.1",
"webpack-hot-middleware": "^2.25.3",
"webpack-manifest-plugin": "^4.0.2"
},
"scripts": {
"prestart": "cp -r ../../build/node_modules/* ./node_modules/",
"prebuild": "cp -r ../../build/node_modules/* ./node_modules/",
"start": "concurrently \"npm run start:server\" \"npm run start:client\"",
"start:client": "NODE_ENV=development BUILD_PATH=dist node scripts/start.js",
"start:server": "NODE_ENV=development BUILD_PATH=dist nodemon -- --experimental-loader ./loader/index.js --conditions=react-server server",
"start:prod": "node scripts/build.js && concurrently \"npm run start:prod-server\" \"npm run start:prod-client\"",
"start:prod-client": "cd ./build && python -m SimpleHTTPServer 3000",
"start:prod-server": "NODE_ENV=production node --experimental-loader ./loader/index.js --conditions=react-server server",
"predev": "cp -r ../../build/oss-experimental/* ./node_modules/",
"prebuild": "cp -r ../../build/oss-experimental/* ./node_modules/",
"dev": "concurrently \"npm run dev:region\" \"npm run dev:global\"",
"dev:global": "NODE_ENV=development BUILD_PATH=dist node --experimental-loader ./loader/global.js server/global",
"dev:region": "NODE_ENV=development BUILD_PATH=dist nodemon --watch src --watch dist -- --experimental-loader ./loader/region.js --conditions=react-server server/region",
"start": "node scripts/build.js && concurrently \"npm run start:region\" \"npm run start:global\"",
"start:global": "NODE_ENV=production node --experimental-loader ./loader/global.js server/global",
"start:region": "NODE_ENV=production node --experimental-loader ./loader/region.js --conditions=react-server server/region",
"build": "node scripts/build.js",
"test": "node scripts/test.js --env=jsdom"
},

Binary file not shown.

After

Width:  |  Height:  |  Size: 24 KiB

View File

@ -1,11 +0,0 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<title>Flight</title>
</head>
<body>
<div id="root"></div>
</body>
</html>

View File

@ -15,9 +15,8 @@ process.on('unhandledRejection', err => {
require('../config/env');
const path = require('path');
const chalk = require('react-dev-utils/chalk');
const chalk = require('chalk');
const fs = require('fs-extra');
const bfj = require('bfj');
const webpack = require('webpack');
const configFactory = require('../config/webpack.config');
const paths = require('../config/paths');
@ -39,7 +38,7 @@ const WARN_AFTER_CHUNK_GZIP_SIZE = 1024 * 1024;
const isInteractive = process.stdout.isTTY;
// Warn and crash if required files are missing
if (!checkRequiredFiles([paths.appHtml, paths.appIndexJs])) {
if (!checkRequiredFiles([paths.appIndexJs])) {
process.exit(1);
}
@ -197,21 +196,13 @@ function build(previousFileSizes) {
warnings: messages.warnings,
};
if (writeStatsJson) {
return bfj
.write(paths.appBuild + '/bundle-stats.json', stats.toJson())
.then(() => resolve(resolveArgs))
.catch(error => reject(new Error(error)));
}
return resolve(resolveArgs);
});
});
}
function copyPublicFolder() {
fs.copySync(paths.appPublic, paths.appBuild, {
fs.copySync('public', 'build', {
dereference: true,
filter: file => file !== paths.appHtml,
});
}

View File

@ -1,154 +0,0 @@
'use strict';
// Do this as the first thing so that any code reading it knows the right env.
process.env.BABEL_ENV = 'development';
process.env.NODE_ENV = 'development';
// Makes the script crash on unhandled rejections instead of silently
// ignoring them. In the future, promise rejections that are not handled will
// terminate the Node.js process with a non-zero exit code.
process.on('unhandledRejection', err => {
throw err;
});
// Ensure environment variables are read.
require('../config/env');
const fs = require('fs');
const chalk = require('react-dev-utils/chalk');
const webpack = require('webpack');
const WebpackDevServer = require('webpack-dev-server');
const clearConsole = require('react-dev-utils/clearConsole');
const checkRequiredFiles = require('react-dev-utils/checkRequiredFiles');
const {
choosePort,
createCompiler,
prepareProxy,
prepareUrls,
} = require('react-dev-utils/WebpackDevServerUtils');
const openBrowser = require('react-dev-utils/openBrowser');
const semver = require('semver');
const paths = require('../config/paths');
const configFactory = require('../config/webpack.config');
const createDevServerConfig = require('../config/webpackDevServer.config');
const getClientEnvironment = require('../config/env');
const react = require(require.resolve('react', {paths: [paths.appPath]}));
const env = getClientEnvironment(paths.publicUrlOrPath.slice(0, -1));
const useYarn = fs.existsSync(paths.yarnLockFile);
const isInteractive = process.stdout.isTTY;
// Warn and crash if required files are missing
if (!checkRequiredFiles([paths.appHtml, paths.appIndexJs])) {
process.exit(1);
}
// Tools like Cloud9 rely on this.
const DEFAULT_PORT = parseInt(process.env.PORT, 10) || 3000;
const HOST = process.env.HOST || '0.0.0.0';
if (process.env.HOST) {
console.log(
chalk.cyan(
`Attempting to bind to HOST environment variable: ${chalk.yellow(
chalk.bold(process.env.HOST)
)}`
)
);
console.log(
`If this was unintentional, check that you haven't mistakenly set it in your shell.`
);
console.log(
`Learn more here: ${chalk.yellow('https://cra.link/advanced-config')}`
);
console.log();
}
// We require that you explicitly set browsers and do not fall back to
// browserslist defaults.
const {checkBrowsers} = require('react-dev-utils/browsersHelper');
checkBrowsers(paths.appPath, isInteractive)
.then(() => {
// We attempt to use the default port but if it is busy, we offer the user to
// run on a different port. `choosePort()` Promise resolves to the next free port.
return choosePort(HOST, DEFAULT_PORT);
})
.then(port => {
if (port == null) {
// We have not found a port.
return;
}
const config = configFactory('development');
const protocol = process.env.HTTPS === 'true' ? 'https' : 'http';
const appName = require(paths.appPackageJson).name;
const useTypeScript = fs.existsSync(paths.appTsConfig);
const urls = prepareUrls(
protocol,
HOST,
port,
paths.publicUrlOrPath.slice(0, -1)
);
// Create a webpack compiler that is configured with custom messages.
const compiler = createCompiler({
appName,
config,
urls,
useYarn,
useTypeScript,
webpack,
});
// Load proxy config
const proxySetting = require(paths.appPackageJson).proxy;
const proxyConfig = prepareProxy(
proxySetting,
paths.appPublic,
paths.publicUrlOrPath
);
// Serve webpack assets generated by the compiler over a web server.
const serverConfig = {
...createDevServerConfig(proxyConfig, urls.lanUrlForConfig),
host: HOST,
port,
};
const devServer = new WebpackDevServer(serverConfig, compiler);
// Launch WebpackDevServer.
devServer.startCallback(() => {
if (isInteractive) {
clearConsole();
}
if (env.raw.FAST_REFRESH && semver.lt(react.version, '16.10.0')) {
console.log(
chalk.yellow(
`Fast Refresh requires React 16.10 or higher. You are using React ${react.version}.`
)
);
}
console.log(chalk.cyan('Starting the development server...\n'));
openBrowser(urls.localUrlForBrowser);
});
['SIGINT', 'SIGTERM'].forEach(function(sig) {
process.on(sig, function() {
devServer.close();
process.exit();
});
});
if (process.env.CI !== 'true') {
// Gracefully exit when stdin ends
process.stdin.on('end', function() {
devServer.close();
process.exit();
});
}
})
.catch(err => {
if (err && err.message) {
console.log(err.message);
}
process.exit(1);
});

View File

@ -1,72 +0,0 @@
'use strict';
const register = require('react-server-dom-webpack/node-register');
register();
const babelRegister = require('@babel/register');
const path = require('path');
babelRegister({
babelrc: false,
ignore: [
/\/(build|node_modules)\//,
function(file) {
if ((path.dirname(file) + '/').startsWith(__dirname + '/')) {
// Ignore everything in this folder
// because it's a mix of CJS and ESM
// and working with raw code is easier.
return true;
}
return false;
},
],
presets: ['react-app'],
plugins: ['@babel/transform-modules-commonjs'],
});
const express = require('express');
const app = express();
// Application
app.get('/', function(req, res) {
require('./handler.server.js')(req, res);
});
app.get('/todos', function(req, res) {
res.setHeader('Access-Control-Allow-Origin', '*');
res.json([
{
id: 1,
text: 'Shave yaks',
},
{
id: 2,
text: 'Eat kale',
},
]);
});
app.listen(3001, () => {
console.log('Flight Server listening on port 3001...');
});
app.on('error', function(error) {
if (error.syscall !== 'listen') {
throw error;
}
var bind = typeof port === 'string' ? 'Pipe ' + port : 'Port ' + port;
switch (error.code) {
case 'EACCES':
console.error(bind + ' requires elevated privileges');
process.exit(1);
break;
case 'EADDRINUSE':
console.error(bind + ' is already in use');
process.exit(1);
break;
default:
throw error;
}
});

View File

@ -0,0 +1,205 @@
'use strict';
// This is a server to host CDN distributed resources like Webpack bundles and SSR
const path = require('path');
// Do this as the first thing so that any code reading it knows the right env.
process.env.BABEL_ENV = process.env.NODE_ENV;
const register = require('react-server-dom-webpack/node-register');
register();
const babelRegister = require('@babel/register');
babelRegister({
babelrc: false,
ignore: [
/\/(build|node_modules)\//,
function (file) {
if ((path.dirname(file) + '/').startsWith(__dirname + '/')) {
// Ignore everything in this folder
// because it's a mix of CJS and ESM
// and working with raw code is easier.
return true;
}
return false;
},
],
presets: ['react-app'],
plugins: ['@babel/transform-modules-commonjs'],
});
// Ensure environment variables are read.
require('../config/env');
const fs = require('fs').promises;
const compress = require('compression');
const chalk = require('chalk');
const express = require('express');
const http = require('http');
const {renderToPipeableStream} = require('react-dom/server');
const {createFromNodeStream} = require('react-server-dom-webpack/client');
const app = express();
app.use(compress());
if (process.env.NODE_ENV === 'development') {
// In development we host the Webpack server for live bundling.
const webpack = require('webpack');
const webpackMiddleware = require('webpack-dev-middleware');
const webpackHotMiddleware = require('webpack-hot-middleware');
const paths = require('../config/paths');
const configFactory = require('../config/webpack.config');
const getClientEnvironment = require('../config/env');
const env = getClientEnvironment(paths.publicUrlOrPath.slice(0, -1));
const config = configFactory('development');
const protocol = process.env.HTTPS === 'true' ? 'https' : 'http';
const appName = require(paths.appPackageJson).name;
// Create a webpack compiler that is configured with custom messages.
const compiler = webpack(config);
app.use(
webpackMiddleware(compiler, {
publicPath: paths.publicUrlOrPath.slice(0, -1),
serverSideRender: true,
})
);
app.use(webpackHotMiddleware(compiler));
}
function request(options, body) {
return new Promise((resolve, reject) => {
const req = http.request(options, res => {
resolve(res);
});
req.on('error', e => {
reject(e);
});
body.pipe(req);
});
}
app.all('/', async function (req, res, next) {
// Proxy the request to the regional server.
const proxiedHeaders = {
'X-Forwarded-Host': req.hostname,
'X-Forwarded-For': req.ips,
'X-Forwarded-Port': 3000,
'X-Forwarded-Proto': req.protocol,
};
// Proxy other headers as desired.
if (req.get('rsc-action')) {
proxiedHeaders['Content-type'] = req.get('Content-type');
proxiedHeaders['rsc-action'] = req.get('rsc-action');
} else if (req.get('Content-type')) {
proxiedHeaders['Content-type'] = req.get('Content-type');
}
const promiseForData = request(
{
host: '127.0.0.1',
port: 3001,
method: req.method,
path: '/',
headers: proxiedHeaders,
},
req
);
if (req.accepts('text/html')) {
try {
const rscResponse = await promiseForData;
let virtualFs;
let buildPath;
if (process.env.NODE_ENV === 'development') {
const {devMiddleware} = res.locals.webpack;
virtualFs = devMiddleware.outputFileSystem.promises;
buildPath = devMiddleware.stats.toJson().outputPath;
} else {
virtualFs = fs;
buildPath = path.join(__dirname, '../build/');
}
// Read the module map from the virtual file system.
const moduleMap = JSON.parse(
await virtualFs.readFile(
path.join(buildPath, 'react-ssr-manifest.json'),
'utf8'
)
);
// Read the entrypoints containing the initial JS to bootstrap everything.
// For other pages, the chunks in the RSC payload are enough.
const mainJSChunks = JSON.parse(
await virtualFs.readFile(
path.join(buildPath, 'entrypoint-manifest.json'),
'utf8'
)
).main.js;
// For HTML, we're a "client" emulator that runs the client code,
// so we start by consuming the RSC payload. This needs a module
// map that reverse engineers the client-side path to the SSR path.
const root = await createFromNodeStream(rscResponse, moduleMap);
// Render it into HTML by resolving the client components
res.set('Content-type', 'text/html');
const {pipe} = renderToPipeableStream(root, {
bootstrapScripts: mainJSChunks,
});
pipe(res);
} catch (e) {
console.error(`Failed to SSR: ${e.stack}`);
res.statusCode = 500;
res.end();
}
} else {
try {
const rscResponse = await promiseForData;
// For other request, we pass-through the RSC payload.
res.set('Content-type', 'text/x-component');
rscResponse.on('data', data => {
res.write(data);
res.flush();
});
rscResponse.on('end', data => {
res.end();
});
} catch (e) {
console.error(`Failed to proxy request: ${e.stack}`);
res.statusCode = 500;
res.end();
}
}
});
if (process.env.NODE_ENV === 'development') {
app.use(express.static('public'));
} else {
// In production we host the static build output.
app.use(express.static('build'));
}
app.listen(3000, () => {
console.log('Global Fizz/Webpack Server listening on port 3000...');
});
app.on('error', function (error) {
if (error.syscall !== 'listen') {
throw error;
}
switch (error.code) {
case 'EACCES':
console.error('port 3000 requires elevated privileges');
process.exit(1);
break;
case 'EADDRINUSE':
console.error('Port 3000 is already in use');
process.exit(1);
break;
default:
throw error;
}
});

View File

@ -1,31 +0,0 @@
'use strict';
const {renderToPipeableStream} = require('react-server-dom-webpack/server');
const {readFile} = require('fs');
const {resolve} = require('path');
const React = require('react');
module.exports = function(req, res) {
// const m = require('../src/App.server.js');
import('../src/App.server.js').then(m => {
const dist = process.env.NODE_ENV === 'development' ? 'dist' : 'build';
readFile(
resolve(__dirname, `../${dist}/react-client-manifest.json`),
'utf8',
(err, data) => {
if (err) {
throw err;
}
const App = m.default.default || m.default;
res.setHeader('Access-Control-Allow-Origin', '*');
const moduleMap = JSON.parse(data);
const {pipe} = renderToPipeableStream(
React.createElement(App),
moduleMap
);
pipe(res);
}
);
});
};

View File

@ -1,4 +1,3 @@
{
"type": "commonjs",
"main": "./cli.server.js"
"type": "commonjs"
}

View File

@ -0,0 +1,199 @@
'use strict';
// This is a server to host data-local resources like databases and RSC
const path = require('path');
const register = require('react-server-dom-webpack/node-register');
register();
const babelRegister = require('@babel/register');
babelRegister({
babelrc: false,
ignore: [
/\/(build|node_modules)\//,
function (file) {
if ((path.dirname(file) + '/').startsWith(__dirname + '/')) {
// Ignore everything in this folder
// because it's a mix of CJS and ESM
// and working with raw code is easier.
return true;
}
return false;
},
],
presets: ['react-app'],
plugins: ['@babel/transform-modules-commonjs'],
});
if (typeof fetch === 'undefined') {
// Patch fetch for earlier Node versions.
global.fetch = require('undici').fetch;
}
const express = require('express');
const bodyParser = require('body-parser');
const busboy = require('busboy');
const app = express();
const compress = require('compression');
const {Readable} = require('node:stream');
app.use(compress());
// Application
const {readFile} = require('fs').promises;
const React = require('react');
async function renderApp(res, returnValue) {
const {renderToPipeableStream} = await import(
'react-server-dom-webpack/server'
);
// const m = require('../src/App.js');
const m = await import('../src/App.js');
let moduleMap;
let mainCSSChunks;
if (process.env.NODE_ENV === 'development') {
// Read the module map from the HMR server in development.
moduleMap = await (
await fetch('http://localhost:3000/react-client-manifest.json')
).json();
mainCSSChunks = (
await (
await fetch('http://localhost:3000/entrypoint-manifest.json')
).json()
).main.css;
} else {
// Read the module map from the static build in production.
moduleMap = JSON.parse(
await readFile(
path.resolve(__dirname, `../build/react-client-manifest.json`),
'utf8'
)
);
mainCSSChunks = JSON.parse(
await readFile(
path.resolve(__dirname, `../build/entrypoint-manifest.json`),
'utf8'
)
).main.css;
}
const App = m.default.default || m.default;
const root = [
// Prepend the App's tree with stylesheets required for this entrypoint.
mainCSSChunks.map(filename =>
React.createElement('link', {
rel: 'stylesheet',
href: filename,
precedence: 'default',
})
),
React.createElement(App),
];
// For client-invoked server actions we refresh the tree and return a return value.
const payload = returnValue ? {returnValue, root} : root;
const {pipe} = renderToPipeableStream(payload, moduleMap);
pipe(res);
}
app.get('/', async function (req, res) {
await renderApp(res, null);
});
app.post('/', bodyParser.text(), async function (req, res) {
const {
renderToPipeableStream,
decodeReply,
decodeReplyFromBusboy,
decodeAction,
} = await import('react-server-dom-webpack/server');
const serverReference = req.get('rsc-action');
if (serverReference) {
// This is the client-side case
const [filepath, name] = serverReference.split('#');
const action = (await import(filepath))[name];
// Validate that this is actually a function we intended to expose and
// not the client trying to invoke arbitrary functions. In a real app,
// you'd have a manifest verifying this before even importing it.
if (action.$$typeof !== Symbol.for('react.server.reference')) {
throw new Error('Invalid action');
}
let args;
if (req.is('multipart/form-data')) {
// Use busboy to streamingly parse the reply from form-data.
const bb = busboy({headers: req.headers});
const reply = decodeReplyFromBusboy(bb);
req.pipe(bb);
args = await reply;
} else {
args = await decodeReply(req.body);
}
const result = action.apply(null, args);
try {
// Wait for any mutations
await result;
} catch (x) {
// We handle the error on the client
}
// Refresh the client and return the value
renderApp(res, result);
} else {
// This is the progressive enhancement case
const UndiciRequest = require('undici').Request;
const fakeRequest = new UndiciRequest('http://localhost', {
method: 'POST',
headers: {'Content-Type': req.headers['content-type']},
body: Readable.toWeb(req),
duplex: 'half',
});
const formData = await fakeRequest.formData();
const action = await decodeAction(formData);
try {
// Wait for any mutations
await action();
} catch (x) {
const {setServerState} = await import('../src/ServerState.js');
setServerState('Error: ' + x.message);
}
renderApp(res, null);
}
});
app.get('/todos', function (req, res) {
res.json([
{
id: 1,
text: 'Shave yaks',
},
{
id: 2,
text: 'Eat kale',
},
]);
});
app.listen(3001, () => {
console.log('Regional Flight Server listening on port 3001...');
});
app.on('error', function (error) {
if (error.syscall !== 'listen') {
throw error;
}
switch (error.code) {
case 'EACCES':
console.error('port 3001 requires elevated privileges');
process.exit(1);
break;
case 'EADDRINUSE':
console.error('Port 3001 is already in use');
process.exit(1);
break;
default:
throw error;
}
});

View File

@ -0,0 +1,47 @@
import * as React from 'react';
import Container from './Container.js';
import {Counter} from './Counter.js';
import {Counter as Counter2} from './Counter2.js';
import ShowMore from './ShowMore.js';
import Button from './Button.js';
import Form from './Form.js';
import {like, greet} from './actions.js';
import {getServerState} from './ServerState.js';
export default async function App() {
const res = await fetch('http://localhost:3001/todos');
const todos = await res.json();
return (
<html lang="en">
<head>
<meta charSet="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<title>Flight</title>
</head>
<body>
<Container>
<h1>{getServerState()}</h1>
<Counter />
<Counter2 />
<ul>
{todos.map(todo => (
<li key={todo.id}>{todo.text}</li>
))}
</ul>
<ShowMore>
<p>Lorem ipsum</p>
</ShowMore>
<Form action={greet} />
<div>
<Button action={like}>Like</Button>
</div>
</Container>
</body>
</html>
);
}

View File

@ -1,28 +0,0 @@
import * as React from 'react';
import {fetch} from 'react-fetch';
import Container from './Container.js';
import {Counter} from './Counter.client.js';
import {Counter as Counter2} from './Counter2.client.js';
import ShowMore from './ShowMore.client.js';
export default function App() {
const todos = fetch('http://localhost:3001/todos').json();
return (
<Container>
<h1>Hello, world</h1>
<Counter />
<Counter2 />
<ul>
{todos.map(todo => (
<li key={todo.id}>{todo.text}</li>
))}
</ul>
<ShowMore>
<p>Lorem ipsum</p>
</ShowMore>
</Container>
);
}

View File

@ -0,0 +1,26 @@
'use client';
import * as React from 'react';
import {experimental_useFormStatus as useFormStatus} from 'react-dom';
import ErrorBoundary from './ErrorBoundary.js';
function ButtonDisabledWhilePending({action, children}) {
const {pending} = useFormStatus();
return (
<button disabled={pending} formAction={action}>
{children}
</button>
);
}
export default function Button({action, children}) {
return (
<ErrorBoundary>
<form>
<ButtonDisabledWhilePending action={action}>
{children}
</ButtonDisabledWhilePending>
</form>
</ErrorBoundary>
);
}

View File

@ -1,3 +1,5 @@
'use client';
import * as React from 'react';
import Container from './Container.js';

View File

@ -1 +0,0 @@
export * from './Counter.client.js';

View File

@ -0,0 +1,3 @@
'use client';
export * from './Counter.js';

View File

@ -0,0 +1,16 @@
'use client';
import * as React from 'react';
export default class ErrorBoundary extends React.Component {
state = {error: null};
static getDerivedStateFromError(error) {
return {error};
}
render() {
if (this.state.error) {
return <div>Caught an error: {this.state.error.message}</div>;
}
return this.props.children;
}
}

View File

@ -0,0 +1,29 @@
'use client';
import * as React from 'react';
import {experimental_useFormStatus as useFormStatus} from 'react-dom';
import ErrorBoundary from './ErrorBoundary.js';
function Status() {
const {pending} = useFormStatus();
return pending ? 'Saving...' : null;
}
export default function Form({action, children}) {
const [isPending, setIsPending] = React.useState(false);
return (
<ErrorBoundary>
<form action={action}>
<label>
Name: <input name="name" />
</label>
<label>
File: <input type="file" name="file" />
</label>
<button>Say Hi</button>
<Status />
</form>
</ErrorBoundary>
);
}

View File

@ -0,0 +1,9 @@
let serverState = 'Hello World';
export function setServerState(message) {
serverState = message;
}
export function getServerState() {
return serverState;
}

View File

@ -1,3 +1,5 @@
'use client';
import * as React from 'react';
import Container from './Container.js';

View File

@ -0,0 +1,20 @@
'use server';
import {setServerState} from './ServerState.js';
export async function like() {
setServerState('Liked!');
return new Promise((resolve, reject) => resolve('Liked'));
}
export async function greet(formData) {
const name = formData.get('name') || 'you';
setServerState('Hi ' + name);
const file = formData.get('file');
if (file) {
return `Ok, ${name}, here is ${file.name}:
${(await file.text()).toUpperCase()}
`;
}
return 'Hi ' + name + '!';
}

Some files were not shown because too many files have changed in this diff Show More