Commit Graph
303 Commits
Author SHA1 Message Date
Colin McDonnellandGitHub 56ffca8b9e Add Bun streaming server renderer (#25597)
Add support for Bun server renderer
2022-11-17 13:15:56 -08:00
mofeiZandGitHub 1a08f1478d [ServerRenderer] Move fizz external runtime implementation to react-dom-bindings (#25617)
<!--
  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
-->

Following
[comment](https://github.com/facebook/react/pull/25437#discussion_r1010944983)
in #25437 , the external runtime implementation should be moved from
`react-dom` to `react-dom-bindings`.

I did have a question here:
I set the entrypoint to `react-dom/unstable_server-external-runtime.js`,
since a.) I was following #25436 as an example and b.)
`react-dom-bindings` was missing a `README.md` and `npm/`. This also
involved adding the external runtime to `package.json`.
However, the external runtime isn't really a `react-dom` entrypoint. Is
this change alright, or should I change the bundling code instead?
## 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.
-->
2022-11-03 11:15:29 -04:00
mofeiZandGitHub 6883d79445 [ServerRenderer] Setup for adding data attributes streaming format (#25567) 2022-11-01 12:04:50 -04:00
Sebastian MarkbågeandGitHub e7c5af45ce Update cache() and use() to the canary aka next channel (#25502)
Testing what it would look like to move this to the `next` channel.
2022-10-23 23:20:52 -04:00
Andrew ClarkandGitHub 9cdf8a99ed [Codemod] Update copyright header to Meta (#25315)
* Facebook -> Meta in copyright

rg --files | xargs sed -i 's#Copyright (c) Facebook, Inc. and its affiliates.#Copyright (c) Meta Platforms, Inc. and affiliates.#g'

* Manual tweaks
2022-10-18 11:19:24 -04:00
Andrew ClarkandGitHub 500bea532d Add option to load Fizz runtime from external file (#25499)
* Add feature flag for external Fizz runtime

Only enabled for www for now

* Add option to load Fizz runtime from external file

When unstable_externalRuntimeSrc is provided, React will inject a script
tag that points to the provided URL.

Then, instead of emitting inline scripts, the Fizz stream will emit
HTML nodes with data attributes that encode the instructions. The
external runtime will detect these with a mutation observer and
translate them into runtime commands. This part isn't implemented in 
this PR, though — all this does is set up the option to use 
an external runtime, and inject the script tag.

The external runtime is injected at the same time as bootstrap scripts.
2022-10-17 17:57:59 -04:00
54f0e0f730 Scaffolding for react-dom/unstable_external-server-runtime (#25482)
* Scaffolding for react-dom/unstable_external-server-runtime

Implements a new bundle type for in our build config called
BROWSER_SCRIPT. This is intended for scripts that get delivered straight
to the browser without needing to be processed by a bundler. (And also
doesn't include any extra UMD crap.)

Right now there's only a single use case so I didn't stress about making
it general purpose.

The use case is: a script that loads the Fizz browser runtime, and sets
up a MutationObserver to receive instructions as HTML streams in. This
will be an alternative option to the default Fizz behavior of sending
the runtime down as inline script tags, to accommodate environments
where inline script tags are not allowed.

There's no development version of this bundle because it doesn't contain
any warnings or run any user code.

None of the actual implementation is in this PR; it just sets up the
build infra.

Co-authored-by: Mofei Zhang <feifei0@fb.com>

* Set BUNDLE_SCRIPT's GCC output format to ES5

This removes the automatic 'use strict' directive, which we don't need.

Co-authored-by: Mofei Zhang <feifei0@fb.com>
2022-10-14 23:29:17 -04:00
Josh StoryandGitHub aa9988e5e6 Server render fork for react-dom (#25436)
Publish an aliasable entry for `react-dom` top level package exports for use in server environments. This is a stub containing only the exports that we expect to retain in the top level once 19 is released
2022-10-10 11:06:22 -07:00
Jan KassensandJan Kassens 00a2f81508 Flow upgrade to 0.143
This was a large upgrade that removed "classic mode" and made "types first" the only option.
Most of the needed changes have been done in previous PRs, this just fixes up the last few instances.

ghstack-source-id: 9612d95ba4
Pull Request resolved: https://github.com/facebook/react/pull/25408
2022-10-04 11:01:50 -04:00
Sebastian MarkbågeandGitHub 97d75c9c8b Move react-dom implementation files to react-dom-bindings (#25345)
This lets us share it with react-server-dom-webpack while still having a
dependency on react-dom. It also makes somewhat sense from a bundling
perspective since react-dom is an external to itself.
2022-09-28 19:05:50 -04:00
Jan KassensandGitHub 5fdcd23aaa Flow: upgrade to 0.140 (#25252)
This update range includes:

- `types_first` ([blog](https://flow.org/en/docs/lang/types-first/), all exports need annotated types) is default. I disabled this for now to make that change incremental.
- Generics that escape the scope they are defined in are an error. I fixed some with explicit type annotations and some are suppressed that I didn't easily figure out.
2022-09-13 13:33:43 -04:00
Jan KassensandGitHub 8003ab9cf5 Flow: remove explicit object syntax (#25223) 2022-09-09 16:03:48 -04:00
Jan KassensandGitHub 8a9e7b6cef Flow: implicit-inexact-object=error (#25210)
* implicit-inexact-object=error
* default everything ambiguous to exact object
* inexact where exact causes errors
2022-09-09 10:13:58 -04:00
Jan KassensandGitHub a473d08fce Update to Flow from 0.97 to 0.122 (#25204)
* flow 0.122
* update ReactModel type
2022-09-08 11:46:07 -04:00
Jan KassensandGitHub f0efa1164b [flow] remove custom suppress comment config (#25170) 2022-09-01 12:55:59 -04:00
Josh StoryandGitHub 1e5245df89 support subresource integrity for bootstrapScripts and bootstrapModules (#25104) 2022-08-17 08:31:05 +01:00
Josh StoryandGitHub 6ef466c681 make preamble and postamble types explicit and fix typo (#25102) 2022-08-16 12:17:49 +01:00
Josh StoryandGitHub 796d31809b Implement basic stylesheet Resources for react-dom (#25060)
Implement basic support for "Resources". In the context of this commit, the only thing that is currently a Resource are

<link rel="stylesheet" precedence="some-value" ...>

Resources can be rendered anywhere in the react tree, even outside of normal parenting rules, for instance you can render a resource before you have rendered the <html><head> tags for your application. In the stream we reorder this so the browser always receives valid HTML and resources are emitted either in place (normal circumstances) or at the top of the <head> (when you render them above or before the <head> in your react tree)

On the client, resources opt into an entirely different hydration path. Instead of matching the location within the Document these resources are queried for in the entire document. It is an error to have more than one resource with the same href attribute.

The use of precedence here as an opt-in signal for resourcifying the link is in preparation for a more complete Resource implementation which will dedupe resource references (multiple will be valid), hoist to the appropriate container (body, head, or elsewhere), order (according to precedence) and Suspend boundaries that depend on them. More details will come in the coming weeks on this plan.

This feature is gated by an experimental flag and will only be made available in experimental builds until some future time.
2022-08-12 13:27:53 -07:00
Andrew ClarkandGitHub 95e22ff528 Delete Partial Renderer SSR implementation (#24868)
This removes the old server rendering implementation (the "Partial Renderer").
It was replaced in React 18 with a new streaming implementation (Fizz).

We hadn't removed it from the codebase yet because Facebook hadn't finished
rolling out Fizz in production; it's been behind a feature flag while we run
performance tests and migrate our internal infrastructure.

The diff to land Fizz will land imminently, and once it does, we can merge
this commit.
2022-07-07 16:57:42 -04:00
Sebastian MarkbågeandGitHub 0f216ae31d Add entry points for "static" server rendering passes (#24752)
This will be used to add optimizations for static server rendering.
2022-06-18 22:34:31 -04:00
Sebastian MarkbågeandGitHub 0f0aca3ab3 Aborting early should not infinitely suspend (#24751)
Before this change we weren't calling onError nor onFatalError if you abort
before completing the shell.

This means that the render never completes and hangs.

Aborting early can happen before even creating the stream for AbortSignal,
before rendering starts in Node since there's an setImmediate atm, or
during rendering.
2022-06-18 11:01:58 -04:00
Sebastian MarkbågeandGitHub 522f47345f Move the Error creation to be lazy (#24728)
Creating an Error captures a stack trace which can be somewhat expensive.
We shouldn't do tthat always for every render.

This also ensures that the stack trace is more useful because you can
follow through the Node.js code to see the cause.
2022-06-14 20:16:42 -04:00
Josh StoryandGitHub b345523528 [Fizz] Support abort reasons (#24680)
* [Fizz] Support abort reasons

Fizz supports aborting the render but does not currently accept a reason. The various render functions that use Fizz have some automatic and some user-controlled abort semantics that can be useful to communicate with the running program and users about why an Abort happened.

This change implements abort reasons for renderToReadableStream and renderToPipeable stream as well as legacy renderers such as renderToString and related implementations.

For AbortController implementations the reason passed to the abort method is forwarded to Fizz and sent to the onError handler. If no reason is provided the AbortController should construct an AbortError DOMException and as a fallback Fizz will generate a similar error in the absence of a reason

For pipeable  streams, an abort function is returned alongside pipe which already accepted a reason. That reason is now forwarded to Fizz and the implementation described above.

For legacy renderers there is no exposed abort functionality but it is used internally and the reasons provided give useful context to, for instance to the fact that Suspense is not supported in renderToString-like renderers
2022-06-07 22:36:09 -07:00
Josh StoryandGitHub bcbeb52bf3 [Fizz] Disallow complex children in <title> elements (#24679)
* [Fizz] Disallow complex children in <title> elements

<title> Elements in the DOM can only have Text content. In Fizz if more than one text node is emitted an HTML comment node is used as a text separator. Unfortunately because of the content restriction of the DOM representation of the title element this separator is displayed as escaped text which is not what the component author intended.

This commit special cases title handling, primarily to issue warnings if you pass complex children to <title>. At the moment title expects to receive a single child or an array of length 1. In both cases the type of that child must be string or number. If anything more complex is provided a warning will be logged to the console explaining why this is problematic.

There is no runtime behavior change so broken things are still broken (e.g. returning two text nodes which will cause a separator or using Suspense inside title children) but they should at least be accompanied by warnings that are useful.

One edge case that will now warn but won't technically break an application is if you use a Component that returns a single string as a child of title. This is a form of indirection that works but becasue we cannot discriminate between a Component that will follow the rules and one that violates them the warning is issued regardless.

* fixup dev warning conditional logic

* lints

* fix bugs
2022-06-07 00:33:36 -07:00
Josh StoryandGitHub 4f29ba1cc5 support errorInfo in onRecoverableError (#24591)
* extend onRecoverableError API to support errorInfo

errorInfo has been used in Error Boundaries wiht componentDidCatch for a while now. To date this metadata only contained a componentStack. onRecoverableError only receives an error (type mixed) argument and thus providing additional error metadata was not possible without mutating user created mixed objects.

This change modifies rootConcurrentErrors rootRecoverableErrors, and hydrationErrors so all expect CapturedValue types. additionally a new factory function allows the creation of CapturedValues from a value plus a hash and stack.

In general, client derived CapturedValues will be created using the original function which derives a componentStack from a fiber and server originated CapturedValues will be created using with a passed in hash and optional componentStack.
2022-06-06 14:23:32 -07:00
Josh LarsonandGitHub 26a5b3c7f7 Explicitly set highWaterMark to 0 for ReadableStream (#24641)
* Explicitly set highWaterMark to 0 for ReadableStreams

This is because not all streaming implementations respect the
default behavior of settings highWaterMark to 0 for byte streams.
Being explicit guarantees the intended behavior across runtimes.

* Remove size methods and add FlowFixMe instead
2022-05-31 16:20:36 -04:00
aec575914a [Fizz] Send errors down to client (#24551)
* use return from onError

* export getSuspenseInstanceFallbackError

* stringToChunk

* return string from onError in downstream type signatures

* 1 more type

* support encoding errors in html stream and escape user input

This commit adds another way to get errors to the suspense instance by encoding them as dataset properties of a template element at the head of the boundary. Previously if there was an error before the boundary flushed there was no way to stream the error to the client because there would never be a client render instruction.

Additionally the error is sent in 3 parts

1) error hash - this is always sent (dev or prod) if one is provided
2) error message - Dev only
3) error component stack - Dev only, this now captures the stack at the point of error

Another item addressed in this commit is the escaping of potentially unsafe data. all error components are escaped as test for browers when written into the html and as javascript strings when written into a client render instruction.

* nits

Co-authored-by: Marco Salazar <salazarm@fb.com>
2022-05-29 23:07:10 -07:00
Josh StoryandGitHub a2766387ef [Fizz] Improve text separator byte efficiency (#24630)
* [Fizz] Improve text separator byte efficiency

Previously text separators were inserted following any Text node in Fizz. This increases bytes sent when streaming and in some cases such as title elements these separators are not interpreted as comment nodes and leak into the visual aspects of a page as escaped text.

The reason simple tracking on the last pushed type doesn't work is that Segments can be filled in asynchronously later and so you cannot know in a single pass whether the preceding content was a text node or not. This commit adds a concept of TextEmbedding which provides a best effort signal to Segments on whether they are embedded within text. This allows the later resolution of that Segment to add text separators when possibly necessary but avoid them when they are surely not.

The current implementation can only "peek" head if the segment is a the Root Segment or a Suspense Boundary Segment. In these cases we know there is no trailing text embedding and we can eliminate the separator at the end of the segment if the last emitted element was Text. In normal Segments we cannot peek and thus have to assume there might be a trailing text embedding and we issue a separator defensively. This should be rare in practice as it is assumed most components that will cause segment creation will also emit some markup at the edges.

* [Fizz] Improve separator efficiency when flushing delayed segments

The method by which we get segment markup into the DOM differs depending on when the Segment resolves.

If a Segment resolves before flushing begins for it's parent it will be emitted inline with the parent markup. In these cases separators may be necessary because they are how we clue the browser into breakup up text into distinct nodes that will later match up with what will be hydrated on the client.

If a Segment resolves after flushing has happened a script will be used to patch up the DOM in the client. when this happens if there are any text nodes on the boundary of the patch they won't be "merged" and thus will continue to have distinct representation as Nodes in the DOM. Thus we can avoid doing any separators at the boundaries in these cases.

After applying these changes the only time you will get text separators as follows

* in between serial text nodes that emit at the same time - these are necessary and cannot be eliminated unless we stop relying on the browser to automatically parse the correct text nodes when processing this HTML
* after a final text node in a non-boundary segment that resolves before it's parent has flushed - these are sometimes extraneous, like when the next emitted thing is a non-Text node.

In all other cases text separators should be omitted which means the general byte efficiency of this approach should be pretty good
2022-05-28 08:30:38 -07:00
Sebastian SilbermannandGitHub 82c64e1a49 Match Preact behavior for boolean props on custom elements (#24541)
* Log unexpected warnings when testing with ReactDOMServerIntegrationTestUtils

* Add test

Following https://github.com/facebook/react/issues/9230#issuecomment-322007671 except that `foo={true}` renders an empty string.
See https://github.com/facebook/react/issues/9230#issuecomment-1123464720 for rationale.

* Match Preact behavior for boolean props on custom elements

* Poke CircleCI
2022-05-20 18:10:43 +01:00
Andrew ClarkandGitHub 392808a1f7 Land enableClientRenderFallbackOnTextMismatch flag (#24405)
This flag is already enabled on all relevant surfaces. We can remove it.
2022-04-20 10:21:36 -04:00
Josh StoryandGitHub 2bf5eba724 explain the rationale for the chosen escaping implemenation in a comment (#24389) 2022-04-16 14:29:12 -07:00
Josh StoryandGitHub d40dc73cf9 Escape bootstrapScriptContent for javascript embedding into HTML (#24385)
The previous escape was for Text into HTML and breaks script contents. The new escaping ensures that the script contents cannot prematurely close the host script tag by escaping script open and close string sequences using a unicode escape substitution.
2022-04-16 10:47:46 -07:00
Sebastian SilbermannandGitHub 548b542b41 Update renderToPipeableStream#options.onShellError to match usage (#24299) 2022-04-07 20:06:54 +01:00
Sebastian MarkbågeandGitHub 4bc465a16f Rename Controls to PipeableStream (#24286)
This type isn't exported so it's technically not public.

This object mimics a ReadableStream.

Currently this is safe to destructure and call separately but I'm not sure
that's even guaranteed. It should probably be treated as a class in docs.
2022-04-06 19:27:38 -04:00
Sebastian MarkbågeandGitHub 796724086a Match select value against primitives to string but not undefined (#24077) 2022-03-12 13:34:55 -05:00
Sebastian SilbermannandGitHub a59f53a603 Fizz: Prevent UnhandledPromiseRejection if shell errors (#24043) 2022-03-08 09:13:47 -05:00
Sebastian MarkbågeandGitHub 14c2be8dac Rename Node SSR Callbacks to onShellReady/onAllReady and Other Fixes (#24030)
* I forgot to call onFatalError

I can't figure out how to write a test for this because it only happens
when there is a bug in React itself which would then be fixed if we found
it.

We're also covered by the protection of ReadableStream which doesn't leak
other errors to us.

* Abort requests if the reader cancels

No need to continue computing at this point.

* Abort requests if node streams get destroyed

This is if the downstream cancels is for example.

* Rename Node APIs for Parity with allReady

The "Complete" terminology is a little misleading because not everything
has been written yet. It's just "Ready" to be written now.

onShellReady
onShellError
onAllReady

* 'close' should be enough
2022-03-04 14:38:46 -05:00
Sebastian MarkbågeandGitHub cb1e7b1c6c Move onCompleteAll to .allReady Promise (#24025)
* Move onCompleteAll to .allReady Promise

The onCompleteAll callback can sometimes resolve before the promise that
returns the stream which is tough to coordinate. A more idiomatic API
for a one shot event is a Promise.

That way the way you render for SEO or SSG is:

const stream = await renderToReadableStream(...);
await stream.readyAll;
respondWith(stream);

Ideally this should be a sub-class of ReadableStream but we don't yet
compile these to ES6 and they'd had to be to native class to subclass
a native stream.

I have other ideas for overriding the .tee() method in a subclass anyway.
So this is inline with that strategy.

* Reject the Promise on fatal errors
2022-03-03 12:46:12 -05:00
Sebastian MarkbågeandGitHub 75662d6a7d Remove hacky stream.locked check, declare as byte stream instead (#23387)
We used to check for stream.locked in pull to see if we've been passed to
something that reads yet.

This was a bad hack because it won't actually call pull again if that changes.

The source of this is because the default for "highWaterMark" is 1 on some
streams. So it always wants to add one "chunk" (of size 1).

If we leave our high water mark as 0, we won't fill up any buffers unless we're
asked for more.

This web API is somewhat odd because it would be way more efficient if it
just told us how much the recipient wants instead of calling us once per
chunk.

Anyway, I turns out that if we define ourselves as a "bytes" type of
stream, the default also happens to be a high water mark of 0 so we can
just use that instead.
2022-02-28 21:35:00 -05:00
Andrew ClarkandGitHub 5d08a24c21 useId: Use 'H' to separate main id from hook index (#23363)
No id should be a subset of any other id. Currently, this is not true
when there are multiple hooks in the same component. We append the
hook index to the end of the id, except for the first one. So you get
this pattern.

Before this change:

- 1st hook's id: :R0:
- 2nd hook's id: :R0:1:

The first hook's id is a subset of all the other ids in the
same component.

The fix for this is to use a different character to separate the main
id from the hook index. I've chosen a captial 'H' for this because
capital letters are not part of the base 32 character set when encoding
with `toString(32)`.

After this change:

- 1st hook's id: :R0:
- 2nd hook's id: :R0H1:
2022-02-25 15:46:59 -05:00
Andrew ClarkandGitHub 3a60844a0f Update error message for suspending at sync priority (#23361)
Instead of adding a new Suspense boundary, the default recommendation
is to wrap the suspending update with startTransition.
2022-02-24 21:02:06 -05:00
Sebastian MarkbågeandGitHub 8d0d0e9a8a Deprecate renderToNodeStream (and fix textarea bug) (#23359)
* Deprecate renderToNodeStream

* Use renderToPipeableStream in tests instead of renderToNodeStream

This is the equivalent API. This means that we have way less test coverage
of this API but I feel like that's fine since it has a deprecation warning
in it and we have coverage on renderToString that is mostly the same.

* Fix textarea bug

The test changes revealed a bug with textarea. It happens because we
currently always insert trailing comment nodes. We should optimize that
away. However, we also don't really support complex children so we
should toString it anyway which is what partial renderer used to do.

* Update tests that assert number of nodes

These tests are unnecessarily specific about number of nodes.

I special case these, which these tests already do, because they're good
tests to test that the optimization actually works later when we do
fix it.
2022-02-24 20:09:03 -05:00
Andrew ClarkandGitHub efe4121ee2 Add : to beginning and end of every useId (#23360)
The ids generated by useId are unique per React root. You can create
additional ids by concatenating them with locally unique strings.

To support this pattern, no id will ever be a subset of another id. We
achieve this by adding a special character to the beginning and end.

We use a colon (":") because it's uncommon — even if you don't prefix
the ids using the `identifierPrefix` option, collisions are unlikely.

One downside of a colon is that it's not a valid character in DOM
selectors, like `querySelectorAll`. We think this is probably
fine because it's not a common use case in React, and there are
workarounds or alternative solutions. But we're open to reconsidering
this in the future if there's a compelling argument.
2022-02-24 20:07:41 -05:00
Sebastian MarkbågeandGitHub 1ad8d81292 Remove object-assign polyfill (#23351)
* Remove object-assign polyfill

We really rely on a more modern environment where this is typically
polyfilled anyway and we don't officially support IE with more extensive
polyfilling anyway. So all environments should have the native version
by now.

* Use shared/assign instead of Object.assign in code

This is so that we have one cached local instance in the bundle.

Ideally we should have a compile do this for us but we already follow
this pattern with hasOwnProperty, isArray, Object.is etc.

* Transform Object.assign to now use shared/assign

We need this to use the shared instance when Object.spread is used.
2022-02-23 19:34:24 -05:00
Sebastian MarkbågeandGitHub 40351575d3 Split writeChunk into void and return value (#23343)
This function was modeled after Node streams where write returns a boolean
whether to keep writing or not. I think we should probably switch this
up and read desired size explicitly in appropriate places.

However, in the meantime, we don't have to return a value where we're
not going to use it. So I split this so that we call writeChunkAndReturn
if we're going to return the boolean.

This should help with the compilation so that they can be inlined.
2022-02-23 11:35:21 -05:00
Sebastian MarkbågeandGitHub 5690932765 Add onErrorShell Callback (#23247)
This indicates that an error has happened before the shell completed and
there's no point in emitting the result of this stream.

This is not quite the same as other fatal errors that can happen even
after streaming as started.

It's also not quite the same as onError before onCompleteShell because
onError can be called for an error inside a Suspense boundary before the
shell completes.

Implement shell error handling in Node SSR fixtures

Instead of hanging indefinitely.

Update Browser Fixture

Expose onErrorShell to the Node build

This API is not Promisified so it's just a separate callback instead.

Promisify the Browser Fizz API

It's now a Promise of a readable stream. The Promise resolves when the
shell completes. If the shell errors, the Promise is rejected.
2022-02-08 22:38:14 -05:00
Joey ArharandGitHub 24dd07bd26 Add custom element property support behind a flag (#22184)
* custom element props

* custom element events

* use function type for on*

* tests, htmlFor

* className

* fix ReactDOMComponent-test

* started on adding feature flag

* added feature flag to all feature flag files

* everything passes

* tried to fix getPropertyInfo

* used @gate and __experimental__

* remove flag gating for test which already passes

* fix onClick test

* add __EXPERIMENTAL__ to www flags, rename eventProxy

* Add innerText and textContent to reservedProps

* Emit warning when assigning to read only properties in client

* Revert "Emit warning when assigning to read only properties in client"

This reverts commit 1a093e584c.

* Emit warning when assigning to read only properties during hydration

* yarn prettier-all

* Gate hydration warning test on flag

* Fix gating in hydration warning test

* Fix assignment to boolean properties

* Replace _listeners with random suffix matching

* Improve gating for hydration warning test

* Add outerText and outerHTML to server warning properties

* remove nameLower logic

* fix capture event listener test

* Add coverage for changing custom event listeners

* yarn prettier-all

* yarn lint --fix

* replace getCustomElementEventHandlersFromNode with getFiberCurrentPropsFromNode

* Remove previous value when adding event listener

* flow, lint, prettier

* Add dispatchEvent to make sure nothing crashes

* Add state change to reserved attribute tests

* Add missing feature flag test gate

* Reimplement SSR changes in ReactDOMServerFormatConfig

* Test hydration for objects and functions

* add missing test gate

* remove extraneous comment

* Add attribute->property test
2021-12-08 15:11:42 +00:00
Andrew ClarkandGitHub 4729ff6d1f Implement identifierPrefix option for useId (#22855)
When an `identifierPrefix` option is given, React will add it to the
beginning of ids generated by `useId`.

The main use case is to avoid conflicts when there are multiple React
roots on a single page.

The server API already supported an `identifierPrefix` option. It's not
only used by `useId`, but also for React-generated ids that are used to
stitch together chunks of HTML, among other things. I added a
corresponding option to the client.

You must pass the same prefix option to both the server and client.
Eventually we may make this automatic by sending the prefix from the
server as part of the HTML stream.
2021-12-02 17:49:43 -08:00
Andrew ClarkandGitHub 75f3ddebfa Remove experimental useOpaqueIdentifier API (#22672)
useId is the updated version of this API.
2021-11-01 15:02:39 -07:00
Andrew ClarkandGitHub ebf9ae8579 useId (#22644)
* Add useId to dispatcher

* Initial useId implementation

Ids are base 32 strings whose binary representation corresponds to the
position of a node in a tree.

Every time the tree forks into multiple children, we add additional bits
to the left of the sequence that represent the position of the child
within the current level of children.

    00101       00010001011010101
    ╰─┬─╯       ╰───────┬───────╯
  Fork 5 of 20       Parent id

The leading 0s are important. In the above example, you only need 3 bits
to represent slot 5. However, you need 5 bits to represent all the forks
at the current level, so we must account for the empty bits at the end.

For this same reason, slots are 1-indexed instead of 0-indexed.
Otherwise, the zeroth id at a level would be indistinguishable from
its parent.

If a node has only one child, and does not materialize an id (i.e. does
not contain a useId hook), then we don't need to allocate any space in
the sequence. It's treated as a transparent indirection. For example,
these two trees produce the same ids:

<>                          <>
  <Indirection>               <A />
    <A />                     <B />
  </Indirection>            </>
  <B />
</>

However, we cannot skip any materializes an id. Otherwise, a parent id
that does not fork would be indistinguishable from its child id. For
example, this tree does not fork, but the parent and child must have
different ids.

<Parent>
  <Child />
</Parent>

To handle this scenario, every time we materialize an id, we allocate a
new level with a single slot. You can think of this as a fork with only
one prong, or an array of children with length 1.

It's possible for the the size of the sequence to exceed 32 bits, the
max size for bitwise operations. When this happens, we make more room by
converting the right part of the id to a string and storing it in an
overflow variable. We use a base 32 string representation, because 32 is
the largest power of 2 that is supported by toString(). We want the base
to be large so that the resulting ids are compact, and we want the base
to be a power of 2 because every log2(base) bits corresponds to a single
character, i.e. every log2(32) = 5 bits. That means we can lop bits off
the end 5 at a time without affecting the final result.

* Incremental hydration

Stores the tree context on the dehydrated Suspense boundary's state
object so it resume where it left off.

* Add useId to react-debug-tools

* Add selective hydration test

Demonstrates that selective hydration works and ids are preserved even
after subsequent client updates.
2021-11-01 13:30:44 -07:00