Commits
main
Name already in use
Commits on Oct 5, 2023
-
pull implementations from the right react-dom (#27471)
should have imported from the stub implementation. this blew up the server rendering stub size (effectively pulling in the entire client bundle)
-
react-dom/server-rendering-stub: restore experimental prefix for `u……seFormState` and `useFormStatus` (#27470) in #27461 the experimental prefix was added back for `useFormState` and `useFormStatus` in react-dom. However these functions are also exported from the server rendering stub too and when using the stub with experimental prefixes their absence causes unexpected errors. This change adds back the experimental prefix for these two hooks to match the experimental build of react-dom.
-
Reduce install network flake (#27464)
## Summary Avoids potentially flaky network calls leading to failures such as https://app.circleci.com/pipelines/github/facebook/react/47096/workflows/b7966c1d-199c-4185-8d17-ac6485235c3a/jobs/727782. Also makes install faster since we don't need the binary in CI seemingly. Electron itself is used to start the standalone binary. ## How did you test this change? - [x] CI still passes without the binary downloaded. I'm just trusting [their docs](https://www.electronjs.org/docs/latest/tutorial/installation) here that setting this actually ensures the binary isn't downloaded.
Commits on Oct 4, 2023
-
[Fizz] Reset error component stack and fix error messages (#27456)
The way we collect component stacks right now are pretty fragile. We expect that we'll call captureBoundaryErrorDetailsDev whenever an error happens. That resets lastBoundaryErrorComponentStackDev to null but if we don't, it just lingers and we don't set it to anything new then which leaks the previous component stack into the next time we have an error. So we need to reset it in a bunch of places. This is still broken with erroredReplay because it has the inverse problem that abortRemainingReplayNodes can call captureBoundaryErrorDetailsDev more than one time. So the second boundary won't get a stack. We probably should try to figure out an alternative way to carry along the stack. Perhaps WeakMap keyed by the error object. This also fixes an issue where we weren't invoking the onShellReady event if we error a replay. That event is a bit weird for resuming because we're probably really supposed to just invoke it immediately if we have already flushed the shell in the prerender which is always atm. Right now, it gets invoked later than necessary because you could have a resumed hole ready before a sibling in the shell is ready and that's blocked.
-
Move ReactCurrentDispatcher back to shared internals (#27462)
The jsx-runtime uses the ReactCurrentDispatcher from shared internals. Recently this was moved to ReactServerSharedInternals which broke jsx-runtime. This change moves it back to ReactSharedInternals until we can come up with a new forking mechanism.
-
Add back temporary
experimental_aliases for Server Actions APIs (#……27461) This adds back the `experimental_`-prefixed Server Actions APIs to the experimental builds only, so that apps that use those don't immediately break when upgrading. The APIs will log a warning to encourage people to move to the unprefixed version, or to switch to the canary release channel. We can remove these in a few weeks after we've given people a chance to upgrade. This does not affect the canary builds at all, since they never had the prefixed versions to begin with.
-
Remove prefix from
formStateoption (#27460)`useFormState` is now in canary.
-
Upgrade Server Actions to canary (#27459)
Upgrades the stability of Server Actions from experimental to canary. - Turns on enableAsyncActions and enableFormActions - Removes "experimental_" prefix from useOptimistic, useFormStatus, and useFormState
-
Warn if optimistic state is updated outside of a transition (#27454)
### Based on #27453 If optimistic state is updated, and there's no startTransition on the stack, there are two likely scenarios. One possibility is that the optimistic update is triggered by a regular event handler (e.g. `onSubmit`) instead of an action. This is a mistake and we will warn. The other possibility is the optimistic update is inside an async action, but after an `await`. In this case, we can make it "just work" by associating the optimistic update with the pending async action. Technically it's possible that the optimistic update is unrelated to the pending action, but we don't have a way of knowing this for sure because browsers currently do not provide a way to track async scope. (The AsyncContext proposal, if it lands, will solve this in the future.) However, this is no different than the problem of unrelated transitions being grouped together — it's not wrong per se, but it's not ideal. Once AsyncContext starts landing in browsers, we will provide better warnings in development for these cases.
-
Remove unreferenced react-native-host-hooks from flow (#27457)
## Summary These modules are no longer referenced in the React codebase. We should remove them to limit the API surface area between React and React Native. ## How did you test this change? `yarn flow native && yarn flow fabric`
Commits on Oct 3, 2023
-
Fix: Optimistic update does not get reset (#27453)
I found a bug where if an optimistic update causes a component to rerender, and there are no other state updates during that render, React bails out without applying the update. Whenever a hook detects a change, we must mark the component as dirty to prevent a bailout. We check for changes by comparing the new state to `hook.memoizedState`. However, when implementing optimistic state rebasing, I incorrectly reset `hook.memoizedState` to the incoming base state, even though I only needed to reset `hook.baseState`. This was just a mistake on my part. This wasn't caught by the existing tests because usually when the optimistic state changes, there's also some other state that marks the component as dirty in the same render. I fixed the bug and added a regression test.
Commits on Oct 2, 2023
-
Fix checkbox and radio hydration (#27401)
Fixes whatever part of #26876 and vercel/next.js#49499 that #27394 didn't fix, probably. From manual tests I believe this behavior brings us back to parity with latest stable release (18.2.0). It's awkward that we keep the user's state even for controlled inputs, so the DOM is out of sync with React state. Previously the .defaultChecked assignment done in updateInput() was changing the actual checkedness because the dirty flag wasn't getting set, meaning that hydrating could change which radio button is checked, even in the absence of user interaction! Now we go back to always detaching again.
-
Fix controlled radios, maybe for real this time (#27443)
Fixes #26876 for real? In 18.2.0 (last stable), we set .checked unconditionally: https://github.com/facebook/react/blob/v18.2.0/packages/react-dom/src/client/ReactDOMInput.js#L129-L135 This is important because if we are updating two radios' checkedness from (false, true) to (true, false), we need to make sure that input2.checked is explicitly set to false, even though setting `input1.checked = true` already unchecks input2. I think this fix is not complete because there is no guarantee that all the inputs rerender at the same time? Hence the TODO. But in practice they usually would and I _think_ this is comparable to what we had before. Also treating function and symbol as false like we used to and like we do on initial mount.
-
This lets a registered object or value be "tainted", which we block from crossing the serialization boundary. It's only allowed to stay in-memory. This is an extra layer of protection against mistakes of transferring data from a data access layer to a client. It doesn't provide perfect protection, because it doesn't trace through derived values and substrings. So it shouldn't be used as the only security layer but more layers are better. `taintObjectReference` is for specific object instances, not any nested objects or values inside that object. It's useful to avoid specific objects from getting passed as is. It ensures that you don't accidentally leak values in a specific context. It can be for security reasons like tokens, privacy reasons like personal data or performance reasons like avoiding passing large objects over the wire. It might be privacy violation to leak the age of a specific user, but the number itself isn't blocked in any other context. As soon as the value is extracted and passed specifically without the object, it can therefore leak. `taintUniqueValue` is useful for high entropy values such as hashes, tokens or crypto keys that are very unique values. In that case it can be useful to taint the actual primitive values themselves. These can be encoded as a string, bigint or typed array. We don't currently check for this value in a substring or inside other typed arrays. Since values can be created from different sources they don't just follow garbage collection. In this case an additional object must be provided that defines the life time of this value for how long it should be blocked. It can be `globalThis` for essentially forever, but that risks leaking memory for ever when you're dealing with dynamic values like reading a token from a database. So in that case the idea is that you pass the object that might end up in cache. A request is the only thing that is expected to do any work. The principle is that you can derive values from out of a tainted entry during a request. Including stashing it in a per request cache. What you can't do is store a derived value in a global module level cache. At least not without also tainting the object.
-
Add feature flag to use microtasks in the React Native Fabric renderer (
#27364) ## Summary This is part of an effort to align the event loop in React Native with its behavior on the Web. In this case, we're going to test enabling microtasks in React Native (Fabric) and we need React to schedule work using microtasks if available there. This just adds a feature flag to configure that behavior at runtime. ## How did you test this change? * Reviewed the generated code, which looks ok. * Did a manual sync of this PR to Meta's internal infra and tested it with my changes to enable microtasks in RN/Hermes.
Commits on Sep 29, 2023
-
[Fizz] Don't double replay elements when it's the postpone point (#27440
) The `resumeElement` function wasn't actually doing the correct thing because it was resuming the element itself but what the child slot means is that we're supposed to resume in the direct child of the element. This is difficult to check for since it's all the possible branches that the element can render into, so instead we just check this in renderNode. It means the hottest path always checks the task which is unfortunate. And also, resuming using the correct nextSegmentId. Fixes two bugs surfaced by this test. --------- Co-authored-by: Josh Story <josh.c.story@gmail.com>
-
Enforce that the "react-server" build of "react" is used (#27436)
I do this by simply renaming the secret export name in the "subset" bundle and this renamed version is what the FlightServer uses. This requires us to be more diligent about always using the correct instance of "react" in our tests so there's a bunch of clean up for that.
-
Bugfix: Selective hydration triggers false update loop error (#27439)
This adds a regression test and fix for a case where a sync update triggers selective hydration, which then leads to a "Maximum update depth exceeded" error, even though there was only a single update. This happens when a single sync update flows into many sibling dehydrated Suspense boundaries. This fix is, if a commit was the result of selective hydration, we should not increment the nested update count, because those renders conceptually are not updates. Ideally, they wouldn't even be in a separate commit — we should be able to hydrate a tree and apply an update on top of it within the same render phase. We could do this once we implement resumable context stacks.
Commits on Sep 28, 2023
-
Pass lanes as argument to performSyncWorkOnRoot (#26763)
`performSyncWorkOnRoot` has only a single caller, and the caller already computes the next lanes (`getNextLanes`) before deciding to call the function. So we can pass them as an argument instead of computing the lanes again. There was already a TODO comment about this, but it was mostly perf related. However, @rickhanlonii noticed a discrepancy where the inner `getNextLanes` call was not being passed the current work-in- progress lanes. Usually this shouldn't matter because there should never be work-in-progress sync work; it should finish immediately. There is one case I'm aware of where we exit the work loop without finishing a sync render, which is selective hydration, but even then it should switch to the sync hydration lane, not the normal sync lane. So something else is probably going on. I suspect it might be related to the `enableUnifiedSyncLane` experiment. This is likely related to a regression found internally at Meta. We're still working on getting a proper regression test; I can come up with a contrived one but I'm not confident it'll be the same as the actual regression until we get a better repro.
-
Test fix: Add missing warning assertion (#27434)
Adds a missing test assertion for Server Context deprecation. The PR that added this warning was based on an older revision than the PR that added the test.
-
Restore "publish
react-server-dom-turbopackto canary channels (#27427 -
Add Server Context deprecation warning (#27424)
As agreed, we're removing Server Context. This was never official documented. We've found that it's not that useful in practice. Often the better options are: - Read things off the url or global scope like params or cookies. - Use the module system for global dependency injection. - Use `React.cache()` to dedupe multiple things instead of computing once and passing down. There are still legit use cases for Server Context but you have to be very careful not to pass any large data, so in generally we recommend against it anyway. Yes, prop drilling is annoying but it's not impossible for the cases this is needed. I would personally always pick it over Server Context anyway. Semantically, Server Context also blocks object deduping due to how it plays out with Server Components that can't be deduped. This is much more important feature. Since it's already in canary along with the rest of RSC, we're adding a warning for a few versions before removing completely to help migration. --------- Co-authored-by: Josh Story <josh.c.story@gmail.com>
Commits on Sep 27, 2023
-
Revert "publish
react-server-dom-turbopackto canary channels (#27427……) (#27428) Build fails because the package does not exist. I've added the package to npm but we need the publishing account to be a collaborator. I'm reverting until we get that sorted so we don't block canaries
-
publish
react-server-dom-turbopackto canary channels (#27427)When I added react-server-dom-turbopack I failed to mark the package as stable so it did not get published with the canary release. This adds the package to the stable set so it will be published correctly
-
[Flight] Implement
react-server-dom-turbopack(#27315)stacked on #27314 Turbopack requires a different module loading strategy than Webpack and as such this PR implements a new package `react-server-dom-turbopack` which largely follows the `react-server-dom-webpack` but is implemented for this new bundler
-
[Flight][Float] Preinitialize module imports during SSR (#27314)
Currently when we SSR a Flight response we do not emit any resources for module imports. This means that when the client hydrates it won't have already loaded the necessary scripts to satisfy the Imports defined in the Flight payload which will lead to a delay in hydration completing. This change updates `react-server-dom-webpack` and `react-server-dom-esm` to emit async script tags in the head when we encounter a modules in the flight response. To support this we need some additional server configuration. We need to know the path prefix for chunk loading and whether the chunks will load with CORS or not (and if so with what configuration).
Commits on Sep 26, 2023
-
[Fizz][Float] Refactor Resources (#27400)
Refactors Resources to have a more compact and memory efficient struture. Resources generally are just an Array of chunks. A resource is flushed when it's chunks is length zero. A resource does not have any other state. Stylesheets and Style tags are different and have been modeled as a unit as a StyleQueue. This object stores the style rules to flush as part of style tags using precedence as well as all the stylesheets associated with the precedence. Stylesheets still need to track state because it affects how we issue boundary completion instructions. Additionally stylesheets encode chunks lazily because we may never write them as html if they are discovered late. The preload props transfer is now maximally compact (only stores the props we would ever actually adopt) and only stores props for stylesheets and scripts because other preloads have no resource counterpart to adopt props into. The ResumableState maps that track which keys have been observed are being overloaded. Previously if a key was found it meant that a resource already exists (either in this render or in a prior prerender). Now we discriminate between null and object values. If map value is null we can assume the resource exists but if it is an object that represents a prior preload for that resource and the resource must still be constructed.
Commits on Sep 25, 2023
-
[Fizz] Track postpones in fallbacks (#27421)
This fixes so that you can postpone in a fallback. This postpones the parent boundary. I track the fallbacks in a separate replay node so that when we resume, we can replay the fallback itself and finish the fallback and then possibly later the content. By doing this we also ensure we don't complete the parent too early since now it has a render task on it. There is one case that this surfaces that isn't limited to prerender/resume but also render/hydrateRoot. I left todos in the tests for this. If you postpone in a fallback, and suspend in the content but eventually don't postpone in the content then we should be able to just skip postponing since the content rendered and we no longer need the fallback. This is a bit of a weird edge case though since fallbacks are supposed to be very minimal. This happens because in both cases the fallback starts rendering early as soon as the content suspends. This also ensures that the parent doesn't complete early by increasing the blocking tasks. Unfortunately, the fallback will irreversibly postpone its parent boundary as soon as it hits a postpone. When you suspend, the same thing happens but we typically deal with this by doing a "soft" abort on the fallback since we don't need it anymore which unblocks the parent boundary. We can't do that with postpone right now though since it's considered a terminal state. I think I'll just leave this as is for now since it's an edge case but it's an annoying exception in the model. Makes me feel I haven't quite nailed it just yet.
-
React DevTools 4.28.3 -> 4.28.4 (#27419)
* refactor[devtools/extension]: refactored messaging logic across different parts of the extension ([hoxyq](https://github.com/hoxyq) in [#27417](#27417)) * fix[devtools/extension]: added a workaround for proxy content script injection in firefox ([hoxyq](https://github.com/hoxyq) in [#27375](#27375)) * fix[devtools/useTransition]: don't check for dispatch property when determining if hook is stateful ([hoxyq](https://github.com/hoxyq) in [#27365](#27365)) * feat[devtools/extension]: show disclaimer when page doesnt run react and refactor react polling logic ([hoxyq](https://github.com/hoxyq) in [#27373](#27373)) * feat:-Added a delete all filters action and added title to the add filter a… ([Biki-das](https://github.com/Biki-das) in [#27332](#27332)) * fix[devtools/extension]: unregister dynamically injected content scripts instead of filtering ([hoxyq](https://github.com/hoxyq) in [#27369](#27369)) * refactor[devtools/extension]: more stable element updates polling to avoid timed out errors ([hoxyq](https://github.com/hoxyq) in [#27357](#27357)) * feat[devtools/extension]: add dark theme for popup ([rakleed](https://github.com/rakleed) in [#27330](#27330))
-
[Fizz] Restrict types of keyPath when it is known (#27418)
When we render an element, we provide the newly created keypath because that means we're never at the root.
-
refactor[devtools/extension]: refactored messaging logic across diffe…
…rent parts of the extension (#27417) 1. bvaughn@9fc04ea#diff-2c5e1f5e80e74154e65b2813cf1c3638f85034530e99dae24809ab4ad70d0143 introduced a vulnerability: we listen to `'fetch-file-with-cache'` event from `window` to fetch sources of the file, in which we want to parse hook names. We send this event via `window`, which means any page can also use this and manipulate the extension to perform some `fetch()` calls. With these changes, instead of transporting message via `window`, we have a distinct content script, which is responsible for fetching sources. It is notified via `chrome.runtime.sendMessage` api, so it can't be manipulated. 2. Consistent structure of messages `{source: string, payload: object}` in different parts of the extension 3. Added some wrappers around `chrome.scripting.executeScript` API in `packages/react-devtools-extensions/src/background/executeScript.js`, which support custom flow for Firefox, to simulate support of `ExecutionWorld.MAIN`.
Commits on Sep 23, 2023
-
[Flight] Dedupe suspense boundaries when it has already been found ea…
…rlier (#27408) If we track a postponed SuspenseBoundary parent that we have to replay through before it has postponed and it postpones itself later, we need to upgrade it to a postponed replay boundary instead of adding two.
-
Ship diffInCommitPhase (#27409)
Performance tests at Meta showed neutral results.
Commits on Sep 22, 2023
-
Stop flowing and then abort if a stream is cancelled (#27405)
We currently abort a stream either it's explicitly told to abort (e.g. by an abortsignal). In this case we still finish writing what we have as well as instructions for the client about what happened so it can trigger fallback cases and log appropriately. We also abort a request if the stream itself cancels. E.g. if you can't write anymore. In this case we should not write anything to the outgoing stream since it's supposed to be closed already now. However, we should still abort the request so that more work isn't performed and so that we can log the reason for it to the onError callback. We should also not do any work after aborting. There we need to stop the "flow" of bytes - so I call stopFlowing in the cancel case before aborting. The tests were testing this case but we had changed the implementation to only start flowing at initial read (pull) instead of start like we used to. As a result, it was no longer covering this case. We have to call reader.read() in the tests to start the flow so that we need to cancel it. We also were missing a final assertion on the error logs and since we were tracking them explicitly the extra error was silenced.
-
fix[devtools/extension]: added a workaround for proxy content script …
…injection in firefox (#27375) Changes: 1. [Firefox-only] For some reason, Firefox might try to inject dynamically registered content script in pages like `about:blank`. I couldn't find a way to change this behaviour, `about:` is not a valid scheme, so we can't exclude it and `match_about_blank` flag is not supported in `chrome.scripting.registerContentScripts`. 2. While navigating the history in Firefox, some content scripts might not be re-injected and still be alive. To handle this, we are now patching `window` with `__REACT_DEVTOOLS_PROXY_INJECTED__` flag, to make sure that proxy is injected and only once. This flag is cleared on `pagehide` event.