Commit Graph

1186 Commits

Author SHA1 Message Date
Andrew Clark
86b3e2461d Implement useSyncExternalStore on server (#22347)
Adds a third argument called `getServerSnapshot`.

On the server, React calls this one instead of the normal `getSnapshot`.
We also call it during hydration.

So it represents the snapshot that is used to generate the initial,
server-rendered HTML. The purpose is to avoid server-client mismatches.
What we render during hydration needs to match up exactly with what we
render on the server.

The pattern is for the server to send down a serialized copy of the
store that was used to generate the initial HTML. On the client, React
will call either `getSnapshot` or `getServerSnapshot` on the client as
appropriate, depending on whether it's currently hydrating.

The argument is optional for fully client rendered use cases. If the
user does attempt to omit `getServerSnapshot`, and the hook is called
on the server, React will abort that subtree on the server and
revert to client rendering, up to the nearest Suspense boundary.

For the userspace shim, we will need to use a heuristic (canUseDOM)
to determine whether we are in a server environment. I'll do that in
a follow up.
2021-09-20 08:31:02 -07:00
Andrew Clark
8209de2695 Delete useMutableSource implementation (#22292)
This API was replaced by useSyncExternalStore
2021-09-19 21:11:50 -07:00
Dan Abramov
67222f044c [Experiment] Warn if callback ref returns a function (#22313) 2021-09-15 13:51:39 +01:00
Ricky
263cfa6ecb [Experimental] Add useInsertionEffect (#21913) 2021-09-14 10:27:09 -04:00
Andrew Clark
8f96c6b2ac [Bugfix] Prevent infinite update loop caused by a synchronous update in a passive effect (#22277)
* Add test that triggers infinite update loop

In 18, passive effects are flushed synchronously if they are the
result of a synchronous update. We have a guard for infinite update
loops that occur in the layout phase, but it doesn't currently work for
synchronous updates from a passive effect.

The reason this probably hasn't come up yet is because synchronous
updates inside the passive effect phase are relatively rare: you either
have to imperatively dispatch a discrete event, like `el.focus`, or you
have to call `ReactDOM.flushSync`, which triggers a warning. (In
general, updates inside a passive effect are not encouraged.)

I discovered this because `useSyncExternalStore` does sometimes
trigger updates inside the passive effect phase.

This commit adds a failing test to prove the issue exists. I will fix
it in the next commit.

* Fix failing test added in previous commit

The way we detect a "nested update" is if there's synchronous work
remaining at the end of the commit phase.

Currently this check happens before we synchronously flush the passive
effects. I moved it to after the effects are fired, so that it detects
whether synchronous work was scheduled in that phase.
2021-09-09 08:14:30 -07:00
Riley Shaw
fbce2d5274 Fix #21972: Add onResize event to video elements (#21973)
* Fix #21972: Add `onResize` event to video elements

This is a simple fix for #21972 that adds support for the `onResize` media event.

I created a separate `videoEventTypes` array since I doubt anyone will want to add `onResize` to an audio event. It would simplify the code a bit to just add `resize` to the `mediaEventTypes` array, if that’s preferred.

Pre-commit checklist ([source](https://reactjs.org/docs/how-to-contribute.html#sending-a-pull-request))

 Fork the repository and create your branch from `main`.
 Run `yarn` in the repository root.
 If you’ve fixed a bug or added code that should be tested, add tests!
 Ensure the test suite passes (`yarn test`). Tip: `yarn test --watch TestName` is helpful in development.
 Run `yarn test --prod` to test in the production environment.
 If you need a debugger, run `yarn debug-test --watch TestName`, open chrome://inspect, and press “Inspect”.
 Format your code with prettier (`yarn prettier`).
 Make sure your code lints (`yarn lint`). Tip: `yarn linc` to only check changed files.
 Run the Flow typechecks (`yarn flow`).
 If you haven’t already, complete the CLA.

* Consolidate `videoEventTypes` array into `mediaEventTypes`
2021-09-07 23:28:19 +01:00
Andrew Clark
77912d9a05 Wire up the native API for useSyncExternalStore (#22237)
Adds useSyncExternalStore to the internal dispatcher, and exports
the native API from the React package without yet implementing it.
2021-09-07 10:20:24 -07:00
Mahyar Ebadi
380284a2b4 Add aria-description to the list of known ARIA attributes (#22142)
* Update validAriaProperties.js

https://w3c.github.io/aria/#aria-description is a valid aria property.

* Sort alphabetically

Co-authored-by: Dan Abramov <dan.abramov@gmail.com>
2021-09-06 20:12:51 +01:00
Konstantin Popov
99f9de9a6a Fix typo in ReactDOMServerFormatConfig.js (#22203)
Fix typo:

TOOD -> TODO
2021-09-06 19:58:46 +01:00
Dan Abramov
7ed0706d7e Remove the warning for setState on unmounted components (#22114)
* Remove warning for setState on unmounted components

* Trigger CI
2021-08-18 21:50:02 +01:00
Sebastian Markbåge
321087d134 [Fizz] Don't add aborted segments to the completedSegments list (#21976)
* Don't add aborted segments to the completedSegments list

* Update error message to include aborted status
2021-07-27 21:53:37 -04:00
Andrew Clark
5c6543771b Fix global reference to Promise (#21926)
Referencing Promise without a type check will throw in environments
where Promise is not defined.

We will follow up with a lint rule that restricts access to all globals
except in dedicated module indirections.
2021-07-20 15:39:57 -07:00
Ricky
310187264d Clean up flushSync flow types (#21887) 2021-07-16 10:37:57 -04:00
Ricky
682bbd0e72 Cache local reference to global Promise (#21886) 2021-07-15 12:39:56 -04:00
Sebastian Silbermann
9090257e6e fix: restore execution context after RetryAfterError completed (#21766)
* test: Add failing test due to executionContext not being restored

* fix: restore execution context after RetryAfterError completed

* Poke codesandbox/ci

* Completely restore executionContext

* expect a specific error
2021-07-13 22:38:25 +01:00
Ricky
14bac6193a Allow components to render undefined (#21869) 2021-07-13 15:48:11 -04:00
Andrew Clark
a4ecd85e86 act: Batch updates, even in legacy roots (#21797)
In legacy roots, if an update originates outside of `batchedUpdates`,
check if it's inside an `act` scope; if so, treat it as if it were
batched. This is only necessary in legacy roots because in concurrent
roots, updates are batched by default.

With this change, the Test Utils and Test Renderer versions of `act` are
nothing more than aliases of the isomorphic API (still not exposed, but
will likely be the recommended API that replaces the others).
2021-07-12 17:15:20 -07:00
Ricky
c2c6ea1fde Capture suspense boundaries with undefined fallbacks (#21854) 2021-07-12 14:50:33 -04:00
Andrew Clark
bfa50f8272 Inline discreteUpdates (#21784)
This API is only used by the event system, to set the event priority for
the scope of a function. We don't need it anymore because we can modify
the priority directly, like we already do for continuous input events.
2021-07-12 07:55:09 -07:00
Andrew Clark
54e88ed12c Bugfix: Flush legacy sync passive effects at beginning of event (#21846)
* Re-land recent flushSync changes

Adds back #21776 and #21775, which were removed due to an internal
e2e test failure.

Will attempt to fix in subsequent commits.

* Failing test: Legacy mode sync passive effects

In concurrent roots, if a render is synchronous, we flush its passive
effects synchronously. In legacy roots, we don't do this because all
updates are synchronous — so we need to flush at the beginning of the
next event. This is how `discreteUpdates` worked.

* Flush legacy passive effects at beginning of event

Fixes test added in previous commit.
2021-07-10 11:15:11 -07:00
Brian Vaughn
9ccc25a0ea Reverting recent flushSync changes (#21816) 2021-07-07 15:07:55 -04:00
Andrew Clark
ed6c091fe9 Replace unbatchedUpdates with flushSync (#21776)
There's a weird quirk leftover from the old Stack (pre-Fiber)
implementation where the initial mount of a leagcy (ReactDOM.render)
root is flushed synchronously even inside `batchedUpdates`.

The original workaround for this was an internal method called
`unbatchedUpdates`. We've since added another API that works almost the
same way, `flushSync`.

The only difference is that `unbatchedUpdates` would not cause other
pending updates to flush too, only the newly mounted root. `flushSync`
flushes all pending sync work across all roots. This was to preserve
the exact behavior of the Stack implementation.

But since it's close enough, let's just use `flushSync`. It's unlikely
anyone's app accidentally relies on this subtle difference, and the
legacy API is deprecated in 18, anyway.
2021-07-01 15:14:07 -07:00
Andrew Clark
32eefcb3c5 Replace flushDiscreteUpdates with flushSync (#21775)
* Replace flushDiscreteUpdates with flushSync

flushDiscreteUpdates is almost the same as flushSync. It forces passive
effects to fire, because of an outdated heuristic, which isn't ideal but
not that important.

Besides that, the only remaining difference between flushDiscreteUpdates
and flushSync is that flushDiscreteUpdates does not warn if you call it
from inside an effect/lifecycle. This is because it might get triggered
by a nested event dispatch, like `el.focus()`.

So I added a new method, flushSyncWithWarningIfAlreadyRendering, which
is used for the public flushSync API. It includes the warning. And I
removed the warning from flushSync, so the event system can call that
one. In production, flushSyncWithWarningIfAlreadyRendering gets inlined
to flushSync, so the behavior is identical.

Another way of thinking about this PR is that I renamed flushSync to
flushSyncWithWarningIfAlreadyRendering and flushDiscreteUpdates to
flushSync (and fixed the passive effects thing). The point is to prevent
these from subtly diverging in the future.

* Invert so the one with the warning is the default one

To make Seb happy
2021-07-01 15:13:00 -07:00
Andrew Clark
c96761c7b2 Delete batchedEventUpdates (#21774)
No longer used anywhere.
2021-06-30 15:09:14 -07:00
Andrew Clark
ae5afb3b9d Simplify discreteUpdates (#21773)
Now that discrete updates are flushed synchronously in a microtask,
the `discreteUpdates` method used by our event system is only a
optimization to save us from having to check `window.event.type` on
every update. So we should be able to remove the extra logic.

Assuming this lands successfully, we can remove `batchedEventUpdates`
and probably inline `discreteUpdates` into the renderer, like we do
for continuous updates.
2021-06-30 11:29:31 -07:00
Dan Abramov
534c9c52ec Move error logging to update callback (#21737)
* Move error logging to update callback

This prevents double logging for gDSFE boundaries with createRoot.

* Add an explanation for the rest of duplicates
2021-06-24 20:57:10 +01:00
Dan Abramov
7fec38041f Log and show error overlay for commit phase errors (#21723)
* Enable skipped tests from #21723

* Report uncaught errors in DEV

* Clear caught error

This is not necessary (as proven by tests) because next invokeGuardedCallback clears it anyway. But I'll keep it for consistency with other calls.
2021-06-24 15:48:28 +01:00
Dan Abramov
e577bfb1ce Add tests for invokeGuardedCallback (#21734)
* Add tests for invokeGuardedCallback

* Add skipped failing tests

* Check next render works

* Mirror tests for createRoot

* Move comments around
2021-06-23 21:47:47 +01:00
Andrew Clark
d7dce572c7 Remove internal act builds from public modules (#21721)
* Move internal version of act to shared module

No reason to have three different copies of this anymore.

I've left the the renderer-specific `act` entry points because legacy
mode tests need to also be wrapped in `batchedUpdates`. Next, I'll update
the tests to use `batchedUpdates` manually when needed.

* Migrates tests to use internal module directly

Instead of the `unstable_concurrentAct` exports. Now we can drop those
from the public builds.

I put it in the jest-react package since that's where we put our other
testing utilities (like `toFlushAndYield`). Not so much so it can be
consumed publicly (nobody uses that package except us), but so it works
with our build tests.

* Remove unused internal fields

These were used by the old act implementation. No longer needed.
2021-06-22 14:29:35 -07:00
Andrew Clark
06f7b4f43a act should work without mock Scheduler (#21714)
Currently, in a React 18 root, `act` only works if you mock the
Scheduler package. This was because we didn't want to add additional
checks at runtime.

But now that the `act` testing API is dev-only, we can simplify its
implementation.

Now when an update is wrapped with `act`, React will bypass Scheduler
entirely and push its tasks onto a special internal queue. Then, when
the outermost `act` scope exists, we'll flush that queue.

I also removed the "wrong act" warning, because the plan is to move
`act` to an isomorphic entry point, simlar to `startTransition`. That's
not directly related to this PR, but I didn't want to bother
re-implementing that warning only to immediately remove it.

I'll add the isomorphic API in a follow up.

Note that the internal version of `act` that we use in our own tests
still depends on mocking the Scheduler package, because it needs to work
in production. I'm planning to move that implementation to a shared
(internal) module, too.
2021-06-22 14:25:07 -07:00
Andrew Clark
422e0bb360 Delete test-utils implementation of act (#21703)
* Delete test-utils implementation of `act`

Since it's dev-only now, we can use the one provided by the reconciler.

* Move act related stuff out of EventInternals
2021-06-22 14:21:22 -07:00
Andrew Clark
bd0a963445 Throw when act is used in production (#21686)
Upgrades the deprecation warning to a runtime error.

I did it this way instead of removing the export so the type is the same
in both builds. It will get dead code eliminated regardless.
2021-06-16 16:29:51 -04:00
Sebastian Markbåge
7ec4c55971 createRoot(..., {hydrate:true}) -> hydrateRoot(...) (#21687)
This adds a new top level API for hydrating a root. It takes the initial
children as part of its constructor. These are unlike other render calls
in that they have to represent what the server sent and they can't be
batched with other updates.

I also changed the options to move the hydrationOptions to the top level
since now these options are all hydration options.

I kept the createRoot one just temporarily to make it easier to codemod
internally but I'm doing a follow up to delete.

As part of this I un-dried a couple of paths. ReactDOMLegacy was intended
to be built on top of the new API but it didn't actually use those root
APIs because there are special paths. It also doesn't actually use most of
the commmon paths since all the options are ignored. It also made it hard
to add only warnings for legacy only or new only code paths.

I also forked the create/hydrate paths because they're subtly different
since now the options are different. The containers are also different
because I now error for comment nodes during hydration which just doesn't
work at all but eventually we'll error for all createRoot calls.

After some iteration it might make sense to break out some common paths but
for now it's easier to iterate on the duplicates.
2021-06-15 13:37:53 -07:00
Sebastian Markbåge
9212d994ba Merge /unstable-fizz entry point into /server (#21684) 2021-06-14 18:37:44 -07:00
Sebastian Markbåge
9343f87203 Use the server src files as entry points for the builds/tests (#21683)
* Use the server src files as entry points for the builds/tests

We need one top level entry point to target two builds so we can't have
the top level one be the entry point for the builds.

* Same thing but with the modern entry point
2021-06-14 16:23:19 -07:00
Sebastian Markbåge
e601854f07 Clean up partial renderer entry points (#21682)
* Clean up partial renderer entry points

I made a mistake by leaving server.browser.stable in which is the partial
renderer for the browser build of stable. That should use the legacy fizz
one.

Since the only usage of the partial renderer now is at FB and we don't use
it with Node, I removed the Node build of partial renderer too.

* Remove GC test

No code is running this path anymore. Ideally this should be ported to
a Fizz form.
2021-06-14 15:44:46 -07:00
Sebastian Markbåge
502f8a2a07 [Fizz/Flight] Don't use default args (#21681)
* Don't use default args

* Hoist out creation for better inlining

The closures prevent inlining otherwise.
2021-06-14 15:28:20 -07:00
Sebastian Markbåge
bd45ad05dc Add a DOCTYPE to the stream if the <html> tag is rendered (#21680)
This makes it a lot easier to render the whole document using React without
needing to patch into the stream.

We expect that currently people will still have to patch into the stream
to do advanced things but eventually the goal is that you shouldn't
need to.
2021-06-14 13:57:17 -07:00
Dan Abramov
a8f5e77b92 Remove invokeGuardedCallback from commit phase (#21666)
* Remove invokeGuardedCallback from commit phase

* Sync fork
2021-06-14 21:45:53 +01:00
Sebastian Markbåge
dbe3363ccd [Fizz] Implement Legacy renderToString and renderToNodeStream on top of Fizz (#21276)
* Wire up DOM legacy build

* Hack to filter extra comments for testing purposes

* Use string concat in renderToString

I think this might be faster. We could probably use a combination of this
technique in the stream too to lower the overhead.

* Error if we can't complete the root synchronously

Maybe this should always error but in the async forms we can just delay
the stream until it resolves so it does have some useful semantics.

In the synchronous form it's never useful though. I'm mostly adding the
error because we're testing this behavior for renderToString specifically.

* Gate memory leak tests of internals

These tests don't translate as is to the new implementation and have been
ported to the Fizz tests separately.

* Enable Fizz legacy mode in stable

* Add wrapper around the ServerFormatConfig for legacy mode

This ensures that we can inject custom overrides without negatively
affecting the new implementation.

This adds another field for static mark up for example.

* Wrap pushTextInstance to avoid emitting comments for text in static markup

* Don't emit static mark up for completed suspense boundaries

Completed and client rendered boundaries are only marked for the client
to take over.

Pending boundaries are still supported in case you stream non-hydratable
mark up.

* Wire up generateStaticMarkup to static API entry points

* Mark as renderer for stable

This shouldn't affect the FB one ideally but it's done with the same build
so let's hope this works.
2021-06-14 12:54:30 -07:00
Andrew Clark
aecb3b6d11 Deprecate ReactDOM.render and ReactDOM.hydrate (#21652)
* Use existing test warning filter for server tests

We have a warning filter for our internal tests to ignore warnings
that are too noisy or that we haven't removed from our test suite yet:
shouldIgnoreConsoleError.

Many of our server rendering tests don't use this filter, though,
because it has its own special of asserting warnings.

So I added the warning filter to the server tests, too.

* Deprecate ReactDOM.render and ReactDOM.hydrate

These are no longer supported in React 18. They are replaced by the
`createRoot` API.

The warning includes a link to documentation of the new API. Currently
it redirects to the corresponding working group post. Here's the PR to
set up the redirect: https://github.com/reactjs/reactjs.org/pull/3730

Many of our tests still use ReactDOM.render. We will need to gradually
migrate them over to createRoot.

In the meantime, I added the warnings to our internal warning filter.
2021-06-09 13:46:55 -07:00
Sebastian Markbåge
e0d9b28999 [Fizz] Minor Fixes for Warning Parity (#21618) 2021-06-03 19:54:31 -04:00
Sebastian Markbåge
1b7b3592f4 [Fizz] Implement Component Stacks in DEV for warnings (#21610)
* Implement component stacks

This uses a reverse linked list in DEV-only to keep track of where we're
currently executing.

* Fix bug that wasn't picking up the right stack at suspended boundaries

This makes it more explicit which stack we pass in to be retained by the
task.
2021-06-03 13:02:41 -07:00
Sebastian Markbåge
2418f24b60 Fix <select> check of defaultValue/value type (#21611) 2021-06-03 09:13:00 -04:00
Sebastian Markbåge
86715efa23 Resolve the true entry point during tests (#21505)
* Resolve the entry point for tests the same way builds do

This way the source tests, test the same entry point configuration.

* Gate test selectors on www

These are currently only exposed in www builds

* Gate createEventHandle / useFocus on www

These are enabled in both www variants but not OSS experimental.

* Temporarily disable www-modern entry point

Use the main one that has all the exports until we fix more tests.

* Remove enableCache override that's no longer correct

* Open gates for www

These used to not be covered because they used Cache which wasn't exposed.
2021-06-02 18:03:29 -07:00
Sebastian Markbåge
8f6163cbed Fix Fizz exported types (#21596) 2021-06-01 10:02:04 -07:00
Pulkit Sharma
0d493dcda9 Removed _debugID field from Fiber - Issue #21558 (#21570)
* Removed _debugID field from Fiber
* Update ReactFunctionComponent-test.js

Co-authored-by: Brian Vaughn <brian.david.vaughn@gmail.com>
2021-05-26 16:53:18 -04:00
Ricky
e0f89aa056 Clean up Scheduler forks (#20915)
* Clean up Scheduler forks

* Un-shadow variables

* Use timer globals directly, add a test for overrides

* Remove more window references

* Don't crash for undefined globals + tests

* Update lint config globals

* Fix test by using async act

* Add test fixture

* Delete test fixture
2021-05-17 16:53:58 -04:00
Sebastian Markbåge
5890e0e692 Remove data-reactroot from server rendering and hydration heuristic (#20996)
This was used to implicitly hydrate if you call ReactDOM.render.

We've had a warning to explicitly use ReactDOM.hydrate(...) instead of
ReactDOM.render(...). We can now remove this from the generated markup.
(And avoid adding it to Fizz.)

This is a little strange to do now since we're trying hard to make the
root API work the same.

But if we kept it, we'd need to keep it in the generated output which adds
unnecessary bytes. It also risks people relying on it, in the Fizz world
where as this is an opportunity to create that clean state.

We could possibly only keep it in the old server rendering APIs but then
that creates an implicit dependency between which server API and which
client API that you use. Currently you can really mix and match either way.
2021-05-13 10:18:21 -07:00
Brian Vaughn
2bf4805e4b Update entry point exports (#21488)
The following APIs have been added to the `react` stable entry point:
* `SuspenseList`
* `startTransition`
* `unstable_createMutableSource`
* `unstable_useMutableSource`
* `useDeferredValue`
* `useTransition`

The following APIs have been added or removed from the `react-dom` stable entry point:
* `createRoot`
* `unstable_createPortal` (removed)

The following APIs have been added to the `react-is` stable entry point:
* `SuspenseList`
* `isSuspenseList`

The following feature flags have been changed from experimental to true:
* `enableLazyElements`
* `enableSelectiveHydration`
* `enableSuspenseServerRenderer`
2021-05-12 11:28:14 -04:00