Uh oh!
There was an error while loading. Please reload this page.
Backport React 19 use API - #32
Draft
christopher-buss wants to merge 65 commits into
Draft
Conversation
Small update to RefObject. Should be backwards compatible with a default of any.
Without export there is no way to use it? 😿 ---------
This PR makes it possible to use `React.Profiler` in production code by setting the `_G.__PROFILE__` flag. In particular, we: 1. Disable `enableProfiling` from SchedulerFeatureFlags.lua to be consistent with [upstream](https://github.com/facebook/react/blob/main/packages/scheduler/src/SchedulerFeatureFlags.js#L10) 3. Disable `enableSchedulerTracing` since it was removed in newer versions [upstream](react/react#20037) 2. Enable `enableProfilerCommitHooks` to be consistent with [upstream](https://github.com/facebook/react/blob/main/packages/shared/ReactFeatureFlags.js#L252-L253) I also deleted an old workflow which was failing OSS leak scan. It was set up to send PR review reminders to a now-defunct channel, so it was obviously not being used. We can add this back later if the team decides they want it in the future. Checklist before submitting: * [ ] Added/updated relevant tests * [ ] Added/updated documentation
…(#427) Allow for setting scheduler flags at runtime. This is needed to support IXP from lua-apps.
This wasn't exported properly
This reverts commit 19253b0.
Adds the root child component name to the "Rendered with fewer hooks than expected" error. This can help narrow down where the error is coming from slightly.
https://roblox.atlassian.net/browse/APPEXP-2466 We see errors logged occasionally when enabling Root-level MP because `profileend` is called when there are no active profiles. This seems to be because profiles automatically end when the frame is yielded, and the previous [fix](https://github.com/Roblox/roact-alignment/pull/413) wasn't sufficient at addressing this. To fix this, we now tally the number of active profiles in the current frame, and check to make sure this number is >=0 before any profileend. Change also bumps FFlagReactMicroprofilerLevel4. To test - I keep the tally code but still let it profileend as it did before. This confirms the error happens when `numActiveProfilesInFrame <= 0`. Also tested with the fix as is, and never see the error. <img width="1183" alt="Screenshot 2025-03-25 at 11 42 59 AM" src="https://github.com/user-attachments/assets/cd817eed-a45d-4230-805e-68d9346765ed" /> Also validate that microprofiler root labeling is still working <img width="500" alt="Screenshot 2025-03-25 at 3 53 12 PM" src="https://github.com/user-attachments/assets/f32d6ae5-9c0f-4b74-a71c-5fcc54a86ac9" />
UIBlox Button component implementation triggered a react warning that setState is called when we render component. However this warning crashed the test because renderingComponentName could be nil. [Apps-fastFlags-allOff] ERR TestService: Error: table index is nil [Apps-fastFlags-allOff] CorePackages.Packages._Index.ReactReconciler.ReactReconciler.ReactFiberWorkLoop.new:3499 [Apps-fastFlags-allOff] CorePackages.Packages._Index.ReactReconciler.ReactReconciler.ReactFiberWorkLoop.new:640 [Apps-fastFlags-allOff] CorePackages.Packages._Index.ReactReconciler.ReactReconciler.ReactFiberHooks.new:1893 function dispatchAction [Apps-fastFlags-allOff] CorePackages.Packages._Index.ReactReconciler.ReactReconciler.ReactFiberHooks.new:1195 [Apps-fastFlags-allOff] CorePackages.Packages._Index.UIBlox.UIBlox.App.SelectionCursor.CursorProvider:82 [Apps-fastFlags-allOff] CorePackages.Packages._Index.UIBlox.UIBlox.App.SelectionCursor.useCursor:9 function useCursor [Apps-fastFlags-allOff] CorePackages.Packages._Index.UIBlox.UIBlox.App.Button.Button:222 [Apps-fastFlags-allOff] CorePackages.Packages._Index.ReactReconciler.ReactReconciler.ReactFiberHooks.new:3124 function renderWithHooks Reproducible when turn on the test in UniversalApp.spec.lua Fixing this table index is nil by giving nil case a default value and improve the getComponentName function for anonymous function
Upgrades CI tools (selene was almost 4 years old)
Upgrades StyLua to support modern Luau features and fixes styles that broke because of the upgrade.
Implements core React Devtools functionality, with lots of outstanding issues and bugs. NOTE TO COMMUNITY: This isn't ready yet!! Please hold your horses!
Adds pcall around unprotected index in typeOf() from react-is to prevent `strict()` wrapped tables from erroring.
Fixes nil exception when changing component props and state from DevTools inspector.
…ools (#445) Fixed element selection from DevTools not working. Closes two tickets in Jira.
…ve Heartbeat event. (#449) Closes (ISSUES HERE). https://roblox.atlassian.net/browse/APPEXP-2466 When some codes yields to a new frame, the existing debug.profilebegin will be cleaned up, so on the react profiling side, we should also reset the state. Before it is using the RenderStepped, it appears too late for some cases, the heartbeat solved this issue.
…n't sync over components and other state (#447) Sets up the `_G.__REACT_DEVTOOLS_ATTACH__` hook so that the React renderer starts collecting data for DevTools immediately, before DevTools actually connects. This should help solve a few use cases (such as profiling on start), but primarily it fixes the bug where launching DevTools after the client starts doesn't sync state up properly.
… set personality to x86_64: Operation not permitted` (#453) ## Problem while working on making benchmarks more stable in Foundation, noticed we have a few things broken in roact-alignment ## Solution - Passing `--privileged` as suggested [here](https://roblox.slack.com/archives/C0112GAH0A1/p1752275111589509?thread_ts=1752272650.441599&cid=C0112GAH0A1) to fix setarch permissions ## Testing before `setarch: failed to set personality to x86_64: Operation not permitted` ([logs](https://github.com/Roblox/roact-alignment/actions/runs/16327087530/job/46119943628)) with `--privileged` ([logs](https://github.com/Roblox/roact-alignment/actions/runs/16275837938/job/45954396993?pr=453)) ``` Run ./bin/run-with-cachegrind.sh ./robloxdev-cli bin/run-first-render-benchmark.lua "FirstRenderCold" 1 | tee -a run-first-render-benchmark-output.txt --597-- warning: L3 cache found, using its data for the LL simulation. --597-- warning: specified LL cache: line_size 64 assoc 11 total_size 25,952,256 --597-- warning: simulated LL cache: line_size 64 assoc 12 total_size 25,165,824 [598:598:20250714,192142.632134:WARNING close_multiple.cc:67] close: Bad file descriptor (9) [598:598:20250714,192142.647548:WARNING close_multiple.cc:67] close: Bad file descriptor (9) [598:598:20250714,192142.648049:WARNING close_multiple.cc:67] close: Bad file descriptor (9) [598:598:20250714,192142.648375:WARNING close_multiple.cc:67] close: Bad file descriptor (9) [598:598:20250714,192142.648677:WARNING close_multiple.cc:67] close: Bad file descriptor (9) [598:598:20250714,192142.648966:WARNING close_multiple.cc:67] close: Bad file descriptor (9) ./bin/run-with-cachegrind.sh: line 56: bc: command not found ``` after using `awk` ``` MountDeepTreeCGCold#TotalInstructionsExecuted x 1115357635.0000000000 executions ±0% (1 runs sampled)(roblox-cli version 0.682.0.682053849c0feadbc2a121e2464839b021c22701a0b1e7f) MountDeepTreeCGCold#L1_InstrReadCacheMisses x 0.0035760000 misses/op ±0% (1 runs sampled)(roblox-cli version 0.682.0.682053849c0feadbc2a121e2464839b021c22701a0b1e7f) MountDeepTreeCGCold#LL_InstrReadCacheMisses x 0.0001560000 misses/op ±0% (1 runs sampled)(roblox-cli version 0.682.0.682053849c0feadbc2a121e2464839b021c22701a0b1e7f) MountDeepTreeCGCold#TotalMemoryReads x 269488858.0000000000 reads ±0% (1 runs sampled)(roblox-cli version 0.682.0.682053849c0feadbc2a121e2464839b021c22701a0b1e7f) MountDeepTreeCGCold#L1_DataReadCacheMisses x 0.0289310000 misses/op ±0% (1 runs sampled)(roblox-cli version 0.682.0.682053849c0feadbc2a121e2464839b021c22701a0b1e7f) MountDeepTreeCGCold#LL_DataReadCacheMisses x 0.0015050000 misses/op ±0% (1 runs sampled)(roblox-cli version 0.682.0.682053849c0feadbc2a121e2464839b021c22701a0b1e7f) MountDeepTreeCGCold#TotalMemoryWrites x 149201992.0000000000 writes ±0% (1 runs sampled)(roblox-cli version 0.682.0.682053849c0feadbc2a121e2464839b021c22701a0b1e7f) MountDeepTreeCGCold#L1_DataWriteCacheMisses x 0.0170560000 misses/op ±0% (1 runs sampled)(roblox-cli version 0.682.0.682053849c0feadbc2a121e2464839b021c22701a0b1e7f) MountDeepTreeCGCold#LL_DataWriteCacheMisses x 0.0090970000 misses/op ±0% (1 runs sampled)(roblox-cli version 0.682.0.682053849c0feadbc2a121e2464839b021c22701a0b1e7f) ```
Ports ReactFreshRuntime.lua and the remainder of ReactFiberHotReloading.new.lua to support HMR. ---------
Closes [UIBLOX-2787](https://roblox.atlassian.net/browse/UIBLOX-2787). Implements a small example app to make testing DevTools and other React features easier. The example app itself is taken from the HMR repo.
### Why are the changes being made? Closes [UIBLOX-2778](https://roblox.atlassian.net/browse/UIBLOX-2778). Fixes a few bugs with native element highlights in Devtools: - We now make sure that an instance is a GuiBase2d before trying to read UI properties - OverlayTip now accounts for a global ZIndex - Focusing the viewport no longer ends selection (e.g. clicking from devtools into studio) - Overlapping highlight rects no longer stack their transparency
### Why are the changes being made? When re-rendering a component using derived state idiom for functional components, if the component had any useCallbacks inside it, React would error with `Rendered more hooks than during the previous render.` when in DEV mode. It looks like this was caused by a mistranslation where instead of calling updateCallback, we would call mountCallback in DEV mode. Note that in non-DEV mode, we already call the correct api (updateCallback) and this seems to be a mistranslation since this was implemented correctly in upstream: https://github.com/facebook/react/blob/43363e2795393a00fd77312a16d6b80e626c29de/packages/react-reconciler/src/ReactFiberHooks.new.js#L2289 Unflagged because it's under DEV mode.
### Why are the changes being made? Closes [UIBLOX-3203](https://roblox.atlassian.net/browse/UIBLOX-3203). Repository facelift! - Clears out the root readme because everything there was outdated and/or not useful for anyone - Rewrites the readme with better branding and no internal jargon - Adds a gitattributes file for luau - Removes the deviations.md file as it was just a to-do file for roact and all were resolved - Removes standalone/ directory because it was unused - Removes the examples/ directory because all the examples were outdated and most showed code style we don't want to encourage - We'll be showing better code examples in the upcoming docs refresh Currently the readme is pretty empty. Once the docs are refreshed the readme can be added to with useful information.
### Why are the changes being made? Closes [UIBLOX-3261](https://roblox.atlassian.net/browse/UIBLOX-3261). Adds a new flag for React to catch any fiber that yields when in DEV mode. Nothing in React supports yielding today, and when you do yield it often results in undefined behaviour. This flag enables an explicit error telling the user that their code is yielding. ### What changes are being made? - Adds `catchYieldingInDEV` feature flag and integrates it into React scheduler to error on yielding within components/hooks during DEV mode - Implements `NoYield` utility to enforce no-yield behavior in callbacks - Updates `ReactFeatureFlags` and adds comprehensive tests for the new yield-catching mechanism --- - [x] AI-assisted summary reviewed and verified by author
### Why are the changes being made? Just cleaning up flags that are completely unused in React today. They have no reference anywhere else in the code. ### What changes are being made? - Removes 13 unused feature flags from the `ReactFeatureFlags` module. - Cleans up related test files to eliminate obsolete feature flag references. - Improves maintainability by reducing dead code and configurations. --- - [x] AI-assisted summary reviewed and verified by author
### Why are the changes being made? Adds documentation to the bulk of React's public API for a better editor experience. ### What changes are being made? - Adds detailed documentation comments to most React public APIs in `react-roblox`, covering functions, hooks, and components. - Enhances code readability and editor support with parameter descriptions, return values, and official React API reference links. --- - [x] AI-assisted summary reviewed and verified by author
### Why are the changes being made? Closes [UIBLOX-3280](https://roblox.atlassian.net/browse/UIBLOX-3280). React stacktraces kinda suck right now. They can be huge and the vast majority of the frames in the stacktrace are from React internal modules. This gets worse the larger the tree is due to React's recursion. This PR: - Introduces a new feature flag for filtering stack frames - Implements a best-effort algorithm for determining if a stack frame is from inside React - Works out the path of known React packages in the datamodel and then checks if the frame is under one of those paths - Does not filter any stack frame if the first stack frame is from inside React (i.e the error originated internally) Before: ``` CorePackages._Workspace.Scheduler.Scheduler.forks.SchedulerHostConfig.default:316: CorePackages._Workspace.Scheduler.Scheduler.forks.SchedulerHostConfig.default:293: ------ Error caught by React ------ Something went very wrong! ------ Error caught by React ------ CorePackages._Workspace.ExampleApp.ExampleApp.someLibraryModule:4 function intentionallyFailingMethod CorePackages._Workspace.ExampleApp.ExampleApp.NameTag:25 function Name CorePackages._Workspace.ReactReconciler.ReactReconciler.ReactFiberHooks.new:3196 function renderWithHooks CorePackages._Workspace.ReactReconciler.ReactReconciler.ReactFiberBeginWork.new:209 function renderWithHooks CorePackages._Workspace.ReactReconciler.ReactReconciler.ReactFiberBeginWork.new:867 function updateFunctionComponent CorePackages._Workspace.ReactReconciler.ReactReconciler.ReactFiberBeginWork.new:3509 function beginWork CorePackages._Workspace.ReactReconciler.ReactReconciler.ReactFiberWorkLoop.new:253 CorePackages._Workspace.Shared.Shared.invokeGuardedCallbackImpl:30 function invokeGuardedCallbackProd CorePackages._Workspace.Shared.Shared.ReactErrorUtils:49 CorePackages._Workspace.ReactReconciler.ReactReconciler.ReactFiberWorkLoop.new:3474 CorePackages._Workspace.ReactReconciler.ReactReconciler.ReactFiberWorkLoop.new:1972 CorePackages._Workspace.ReactReconciler.ReactReconciler.ReactFiberWorkLoop.new:1860 CorePackages._Workspace.ReactReconciler.ReactReconciler.ReactFiberWorkLoop.new:1809 CorePackages._Workspace.ReactReconciler.ReactReconciler.ReactFiberWorkLoop.new:942 CorePackages._Workspace.ReactReconciler.ReactReconciler.ReactFiberWorkLoop.new:858 CorePackages._Workspace.Scheduler.Scheduler.Scheduler:320 CorePackages._Workspace.Scheduler.Scheduler.Scheduler:268 CorePackages._Workspace.Scheduler.Scheduler.forks.SchedulerHostConfig.default:241 function doWork CorePackages._Workspace.Scheduler.Scheduler.forks.SchedulerHostConfig.default:277 function performWorkUntilDeadline ``` After: ``` CorePackages._Workspace.Scheduler.Scheduler.forks.SchedulerHostConfig.default:316: CorePackages._Workspace.Scheduler.Scheduler.forks.SchedulerHostConfig.default:293: ------ Error caught by React ------ Something went very wrong! ------ Error caught by React ------ CorePackages._Workspace.ExampleApp.ExampleApp.someLibraryModule:4 function intentionallyFailingMethod CorePackages._Workspace.ExampleApp.ExampleApp.NameTag:25 function Name ``` ### What changes are being made? - Adds `filterInternalStackFrames` feature flag to exclude React internal stack frames from error traces for improved readability. - Implements `buildStackString` function to construct filtered stack traces by identifying and omitting known React internal modules. - Updates `describeError` to apply stack frame filtering based on the new feature flag while preserving unfiltered errors from React internals. --- - [x] AI-assisted summary reviewed and verified by author
### Why are the changes being made? Closes [UIBLOX-3163](https://roblox.atlassian.net/browse/UIBLOX-3163). Updates DevTools to use the new user-space WebSocket API that's developer-accessible in Studio. This unblocks a couple of internal teams adopting DevTools, and will allow the wider community to use it as well. This change is flagged behind `ReactDevtoolsUseHttpWebStream` because I'd like to get it out sooner rather than later, but releasing it without waiting a few weeks will probably break some internal workflows (e.g. people on an outdated version of studio). Once the new API has been live for a month or so I'll come back and clean up the flag. ### What changes are being made? - Updates DevTools to use `HttpService:CreateWebStreamClient` and renders GUI in `Players.LocalPlayer.PlayerGui` with adjusted `App.lua` GUI properties for user-space compatibility. --- - [x] AI-assisted summary reviewed and verified by author
As mentioned in #488 we noticed that the rotriever version used in the repo is so old that one of the bugs in it was causing non-publish packages to become published. This PR bumps the rotriever version to pull in any more modern bugfixes and features :)
While working on publishing this repo to the Creator Store, I noticed that some `publish = true` packages depend on the following `publish = false` packages: - `modules/react-noop-renderer` - `modules/scheduler` - `modules/shared` This breaks our Creator Store publishing workflow as we assume `publish = false` packages should not be included in the final build, but depending on them from a `publish = true` package conflicts with this. Furthermore, it turns out the rotriever version used in this repo is old enough that this setting isn't respected anyway, so all of the nonpublish packages are, in fact, published: https://rotriever.simulprod.com/package/Shared So this PR removes the `publish = false` declarations from the rotriever TOMLs since they aren't doing anything (except breaking our automation!) and don't seem to make sense anyway given they're publicly depended upon. It is better to have these TOMLs reflect their actual behaviour so that rotriever can be safely updated in the future without stopping updates from being pushed to the registry.
### Why are the changes being made? Updates the documentation site to use the new `react-luau.dev` URL. ### What changes are being made? - Updates `mkdocs.yml` site metadata (site name, URL, repo) and fixes `nav` indentation for nested pages. --- - [x] AI-assisted summary reviewed and verified by author
### Why are the changes being made? Updates the error message when a component yields in DEV mode to more clearly explain the error and point the user towards the doc on yielding. ### What changes are being made? - Updates DEV no-yield error in `NoYield.lua` to multi-line; explains yields stall scheduler and links `go/react-yield-error` --- - [ ] AI-assisted summary reviewed and verified by author
Implements react/react#21039 on our codebase. Creates a new deleted tree clean up level with three distinct levels. Facebook did an experiment and found level 3 to be the best, we should do the same and see whether the existing path, 1, 2, or 3 is the best.
Rotriever requires readmes for publishing now. Added stubs.
lute versions was too old, foreman couldn't even see it https://github.com/Roblox/roact-alignment/actions/runs/23354471638/job/67941642914 Checklist before submitting: * [ ] Added/updated relevant tests * [ ] Added/updated documentation
Adds a more comprehensive Wally exclude list and bumps the version number for the use of other packages.
## Summary - Add runtime scheduler config fields for desired and minimum frame rates. - Reset scheduler frame budget state when those frame-rate overrides change. - Bump the workspace Rotriever patch version for the Scheduler package change. ## Test plan - ReadLints on `modules/scheduler/src/forks/SchedulerHostConfig.default.lua` and `rotriever.toml`. Made with [Cursor](https://cursor.com) ---------
Turns out Jest needs this one, so we're publishing it to Wally :)
Removes Wally from the Foreman TOML as no internal workflows should depend on Wally, only Rotriever.
Rotriever takes its version from the single `[workspace] version` in rotriever.toml, while Wally takes one from each modules/*/wally.toml. Nothing keeps the two in sync and they had drifted: rotriever.toml was bumped to 17.3.10 alongside the scheduler frame-rate change, but no Wally manifest was, so a Rotriever publish and a Wally publish from the same commit emitted different version numbers. That drift also means 17.3.10 no longer identifies one payload. A 17.3.10 was hand-published to wally-test-index before the scheduler change landed, so on Wally that number names the older code while on Rotriever it names the newer. Wally releases have meanwhile been stuck at 17.3.9, which the index rejects as already published on every run. Move both version sources to 17.3.11 so a single number means one thing on every registry, rather than trying to reconcile 17.3.10 on indices that do not allow republishing.
Co-authored-by: Codex <noreply@openai.com>
christopher-buss
marked this pull request as draft
August 31, 2026 21:23
Load the thenable helper inside the two error paths so Studio debug.loadmodule can compile the near-limit WorkLoop chunk. Co-authored-by: Codex <noreply@openai.com>
Document the React 17 replay and thenable-tracking divergences, correct pinned source ranges, and make the test ledger match the actual port. Port the fulfilled-thenable regression and preserve observable scheduler yield order across the translated use cases. Co-authored-by: Codex <noreply@openai.com>
Match the upstream warning count and text contract while allowing React 17's console harness to append the component stack. Co-authored-by: Codex <noreply@openai.com>
Use the upstream development wrapper and production array shapes without an unnecessary React-Luau deviation. Co-authored-by: Codex <noreply@openai.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for freeto join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
use(Context)and cached Promise-compatible thenable readsusecalls without normal Hook orderingCompatibility boundary
This is the client cached-Promise API. Promises must be created and cached outside render, must settle normally, and expose
andThen. React 19 server/RSC behavior, cache APIs, hydration, sibling prewarming, Actions, Promise-as-child, async components, and uncached component replay are excluded. Roblox Promise cancellation is unsupported because ordinaryandThenlisteners are not notified reliably.React-Luau 17 has no React 19
SuspendedOnImmediatereplay state machine. The opaqueuseexception is therefore converted before the existing unwind, Suspense capture, ping, and retry path; the cached Promise's instrumented status survives the retry.Provenance
ae74234eae6ebd62f19190731278e20bc1c37d51ReactUse-test.jslines 534-568: exactly one warning containing the complete upstream texttoErrorDevassertion validates the stack instead of incorrectly requiring its absence; this adaptation is marked at the test siteThe implementation and complete test/deviation classification are pinned in
docs/backports/react-19-use.md.Verification
Exact candidate:
cf0a258d87d06fb09f13fb549f5564d1123f77d6/ treef82a837524a8281e9c3af8c6e8450124b056bc7728c57e5d4ab256956980c4fd3bf9f4d3c865630e: identity 1/1; ReactUse 13/14, with the expected warning text/count and component stack rejected only by the unsupported no-stack matcher optiondebug.loadmodulererun: identity 1/1 and complete ReactUse 14/14, including the try/catch warning regression1E1168AB3994E61A079852A148CCD70E4965C1C65374EF31E729337CBF92B59F2302E858AE23831EBBE5FF0BFF2A351940F97CF6CEFE78C733940E835910457DA5800572BCEBADA709F02E0BA9C9E486EEC8919B40CBCDBFD7D5D71BF07E7C71FAEEADA030DAA0BC6D41CBB8085E1CED9E3A1F3E13E7FA81FD2B6D03A5050E67D9984A6FE84B2A031B55DA85B5470C88EFAF73C4F7819C3434FA3159F8E84A59bin/ci.sh: dependency installation, Roblox analysis, and DEV/release runtime stages remain unavailable locally because the pinned Roblox-internal Foreman sources and required CLI binaries are not accessibleGenerated with Codex.