fix: catch parameter alias handling and snapshot updates for noBackwardRangeExtension#1
Closed
fresh3nough wants to merge 46 commits intomainfrom
Closed
fix: catch parameter alias handling and snapshot updates for noBackwardRangeExtension#1fresh3nough wants to merge 46 commits intomainfrom
fresh3nough wants to merge 46 commits intomainfrom
Conversation
Follow up to facebook#35630 We don't currently have any operations that depend on the updating of text nodes added or removed after Fragment mount. But for the sake of completeness and extending the ability to any other host configs, this change calls `commitNewChildToFragmentInstance` and `deleteChildFromFragmentInstance` on HostText fibers. Both DOM and Fabric configs early return because we cannot attach event listeners or observers to text. In the future, there could be some stateful Fragment feature that uses text that could extend this.
Handles TODOs, small follow up refactors
…5763) ## Overview While building the RSC sandboxes I notice error messages like: > An error occurred in the `<Offscreen>` component This is an internal component so it should show either: > An error occurred in the `<Suspense>` component. > An error occurred in the `<Activity>` component. It should only happen when there's a lazy in the direct child position of a `<Suspense>` or `<Activity>` component.
…ated code (facebook#35755) This is unused.
…ren before removing (facebook#35775) Currently, this silently removes the last child in the list, which doesn't contain the `id`.
## Summary ESLint v10.0.0 was released on February 7, 2026. The current `peerDependencies` for `eslint-plugin-react-hooks` only allows up to `^9.0.0`, which causes peer dependency warnings when installing with ESLint v10. This PR: - Adds `^10.0.0` to the eslint peer dependency range - Adds `eslint-v10` to devDependencies for testing - Adds an `eslint-v10` e2e fixture (based on the existing `eslint-v9` fixture) ESLint v10's main breaking changes (removal of legacy eslintrc config, deprecated context methods) don't affect this plugin - flat config is already supported since v7.0.0, and the deprecated APIs already have fallbacks in place. ## How did you test this change? Ran the existing unit test suite: ``` cd packages/eslint-plugin-react-hooks && yarn test ``` All 5082 tests passed.
…ion (facebook#35795) When the Flight Client resolves chunk references during model parsing, it calls `transferReferencedDebugInfo` to propagate debug info entries from referenced chunks to the parent chunk. Debug info on chunks is later moved to their resolved values, where it is used by React DevTools to show performance tracks and what a component was suspended by. Debug chunks themselves (specifically `ReactComponentInfo`, `ReactAsyncInfo`, `ReactIOInfo`, and their outlined references) are metadata that is never rendered. They don't need debug info attached to them. Without this fix, debug info entries accumulate on outlined debug chunks via their references to other debug chunks (e.g. owner chains and props deduplication paths). Since each outlined chunk's accumulated entries are copied to every chunk that references it, this creates exponential growth in deep component trees, which can cause the dev server to hang and run out of memory. This generalizes the existing skip of `transferReferencedDebugInfo` for Element owner/stack references (which already recognizes that references to debug chunks don't need debug info transferred) to all references resolved during debug info resolution. It adds an `isInitializingDebugInfo` flag set in `initializeDebugChunk` and `resolveIOInfo`, which propagates through all nested `initializeModelChunk` calls within the same synchronous stack. For the async path, `waitForReference` captures the flag at call time into `InitializationReference.isDebug`, so deferred fulfillments also skip the transfer.
Tracks locations for reactive scope dependencies, both on the deps and portions of the path. The immediate need for this is a non-public experiment where we're exploring type-directed compilation, and sometimes look up the types of expressions by location. We need to preserve locations accurately for that to work, including the locations of the deps. ## Test Plan Locations for dependencies are not easy to test: i manually spot-checked the new fixture to ensure that the deps look right. This is fine as best-effort since it doesn't impact any of our core compilation logic, i may fix forward if there are issues and will think about how to test.
…ok#35780) ## Summary Add "RCTSelectableText" to the list of component names recognized as being inside a text element, alongside "RCTText". React Native's new text stack, tries to optimize and allows differentiating between a custom TextView, with lower level control, that can reuse the work performed during Fabric/Yoga layout, and a native TextView, used for fidelity. On Android at least, the only place we've needed native TextView for fidelity/native UX has been support for `selectable` text, which has many unique UI interactions. ## How did you test this change? When I patch this in, alongside facebook/react-native#55552, we no longer see warnings when we render text inside of RCTSelectableText component. --------- Co-authored-by: Eli White <github@eli-white.com>
…yload (facebook#35776) ## Summary Follow-up to vercel/next.js#89823 with the actual changes to React. Replaces the `JSON.parse` reviver callback in `initializeModelChunk` with a two-step approach: plain `JSON.parse()` followed by a recursive `reviveModel()` post-process (same as in Flight Reply Server). This yields a **~75% speedup** in RSC chunk deserialization. | Payload | Original (ms) | Walk (ms) | Speedup | |---------|---------------|-----------|---------| | Small (2 elements, 142B) | 0.0024 | 0.0007 | **+72%** | | Medium (~12 elements, 914B) | 0.0116 | 0.0031 | **+73%** | | Large (~90 elements, 16.7KB) | 0.1836 | 0.0451 | **+75%** | | XL (~200 elements, 25.7KB) | 0.3742 | 0.0913 | **+76%** | | Table (1000 rows, 110KB) | 3.0862 | 0.6887 | **+78%** | ## Problem `createFromJSONCallback` returns a reviver function passed as the second argument to `JSON.parse()`. This reviver is called for **every key-value pair** in the parsed JSON. While the logic inside the reviver is lightweight, the dominant cost is the **C++ → JavaScript boundary crossing** — V8's `JSON.parse` is implemented in C++, and calling back into JavaScript for every node incurs significant overhead. Even a trivial no-op reviver `(k, v) => v` makes `JSON.parse` **~4x slower** than bare `JSON.parse` without a reviver: ``` 108 KB payload: Bare JSON.parse: 0.60 ms Trivial reviver: 2.95 ms (+391%) ``` ## Change Replace the reviver with a two-step process: 1. `JSON.parse(resolvedModel)` — parse the entire payload in C++ with no callbacks 2. `reviveModel` — recursively walk the resulting object in pure JavaScript to apply RSC transformations The `reviveModel` function includes additional optimizations over the original reviver: - **Short-circuits plain strings**: only calls `parseModelString` when the string starts with `$`, skipping the vast majority of strings (class names, text content, etc.) - **Stays entirely in JavaScript** — no C++ boundary crossings during the walk ## Results You can find the related applications in the [Next.js PR ](vercel/next.js#89823 I've been testing this on Next.js applications. ### Table as Server Component with 1000 items Before: ``` "min": 13.782875000000786, "max": 22.23400000000038, "avg": 17.116868530000083, "p50": 17.10766700000022, "p75": 18.50787499999933, "p95": 20.426249999998618, "p99": 21.814125000000786 ``` After: ``` "min": 10.963916999999128, "max": 18.096083000000363, "avg": 13.543286884999988, "p50": 13.58350000000064, "p75": 14.871791999999914, "p95": 16.08429099999921, "p99": 17.591458000000785 ``` ### Table as Client Component with 1000 items Before: ``` "min": 3.888875000000553, "max": 9.044959000000745, "avg": 4.651271475000067, "p50": 4.555749999999534, "p75": 4.966624999999112, "p95": 5.47754200000054, "p99": 6.109499999998661 ```` After: ``` "min": 3.5986250000005384, "max": 5.374291000000085, "avg": 4.142990245000046, "p50": 4.10570799999914, "p75": 4.392041999999492, "p95": 4.740084000000934, "p99": 5.1652500000000146 ``` ### Nested Suspense Before: ``` Requests: 200 Min: 73ms Max: 106ms Avg: 78ms P50: 77ms P75: 80ms P95: 85ms P99: 94ms ``` After: ``` Requests: 200 Min: 56ms Max: 67ms Avg: 59ms P50: 58ms P75: 60ms P95: 65ms P99: 66ms ``` ### Even more nested Suspense (double-level Suspense) Before: ``` Requests: 200 Min: 159ms Max: 208ms Avg: 169ms P50: 167ms P75: 173ms P95: 183ms P99: 188ms ``` After: ``` Requests: 200 Min: 125ms Max: 170ms Avg: 134ms P50: 132ms P75: 138ms P95: 148ms P99: 160ms ``` ## How did you test this change? Ran it across many Next.js benchmark applications. The entire Next.js test suite passes with this change. --------- Co-authored-by: Hendrik Liebau <mail@hendrik-liebau.de>
…sh (facebook#35824) When flushing the shell, stylesheets with precedence are emitted in the `<head>` which blocks paint regardless. Outlining a boundary solely because it has suspensey CSS provides no benefit during the shell flush and causes a higher-level fallback to be shown unnecessarily (e.g. "Middle Fallback" instead of "Inner Fallback"). This change passes a flushingInShell flag to hasSuspenseyContent so the host config can skip stylesheet-only suspensey content when flushing the shell. Suspensey images (used for ViewTransition animation reveals) still trigger outlining during the shell since their motivation is different. When flushing streamed completions the behavior is unchanged — suspensey CSS still causes outlining so the parent content can display sooner while the stylesheet loads.
Cleans up feature flags that do not have an active experiment and which we don't currently plan to ship, one commit per flag. Notable removals: * Automatic (inferred) effect dependencies / Fire: abandoned due to early feedback. Shipped useEffectEvent which addresses some of the use-cases. * Inline JSX transform (experimented, not a consistent win) * Context selectors (experimented, not a sufficient/consistent win given the benefit the compiler already provides) * Instruction Reordering (will try a different approach) To decide which features to remove, I looked at Meta's internal repos as well as eslint-pugin-react-hooks to see which flags were never overridden anywhere. That gave a longer list of flags, from which I then removed some features that I know are used in OSS.
…ok#35839) When a Suspense boundary suspends during initial mount, the primary children's fibers are discarded because there is no current tree to preserve them. If the suspended promise never resolves, the only way to retry is something external like a context change. However, lazy context propagation could not find the consumer fibers — they no longer exist in the tree — so the Suspense boundary was never marked for retry and remained stuck in fallback state indefinitely. The fix teaches context propagation to conservatively mark suspended Suspense boundaries for retry when a parent context changes, even when the consumer fibers can't be found. This matches the existing conservative approach used for dehydrated (SSR) Suspense boundaries.
…5827) Remove dead code left behind after the removal of retryCompileFunction, enableFire, and inferEffectDependencies: - Delete ValidateNoUntransformedReferences.ts (always a no-op) - Remove CompileProgramMetadata type and retryErrors from ProgramContext - Remove 'client-no-memo' output mode - Change compileProgram return type from CompileProgramMetadata | null to void
Add detailed plan for making the React Compiler fault-tolerant by accumulating errors across all passes instead of stopping at the first error. This enables reporting multiple compilation errors at once. --- [//]: # (BEGIN SAPLING FOOTER) Stack created with [Sapling](https://sapling-scm.com). Best reviewed with [ReviewStack](https://reviewstack.dev/facebook/react/pull/35872). * facebook#35888 * facebook#35884 * facebook#35883 * facebook#35882 * facebook#35881 * facebook#35880 * facebook#35879 * facebook#35878 * facebook#35877 * facebook#35876 * facebook#35875 * facebook#35874 * facebook#35873 * __->__ facebook#35872
…ent (facebook#35873) Add error accumulation methods to the Environment class: - #errors field to accumulate CompilerErrors across passes - recordError() to record a single diagnostic (throws if Invariant) - recordErrors() to record all diagnostics from a CompilerError - hasErrors() to check if any errors have been recorded - aggregateErrors() to retrieve the accumulated CompilerError - tryRecord() to wrap callbacks and catch CompilerErrors --- [//]: # (BEGIN SAPLING FOOTER) Stack created with [Sapling](https://sapling-scm.com). Best reviewed with [ReviewStack](https://reviewstack.dev/facebook/react/pull/35873). * facebook#35888 * facebook#35884 * facebook#35883 * facebook#35882 * facebook#35881 * facebook#35880 * facebook#35879 * facebook#35878 * facebook#35877 * facebook#35876 * facebook#35875 * facebook#35874 * __->__ facebook#35873
…erance (facebook#35874) - Change runWithEnvironment/run/compileFn to return Result<CodegenFunction, CompilerError> - Wrap all pipeline passes in env.tryRecord() to catch and record CompilerErrors - Record inference pass errors via env.recordErrors() instead of throwing - Handle codegen Result explicitly, returning Err on failure - Add final error check: return Err(env.aggregateErrors()) if any errors accumulated - Update tryCompileFunction and retryCompileFunction in Program.ts to handle Result - Keep lint-only passes using env.logErrors() (non-blocking) - Update 52 test fixture expectations that now report additional errors This is the core integration that enables fault tolerance: errors are caught, recorded, and the pipeline continues to discover more errors. --- [//]: # (BEGIN SAPLING FOOTER) Stack created with [Sapling](https://sapling-scm.com). Best reviewed with [ReviewStack](https://reviewstack.dev/facebook/react/pull/35874). * facebook#35888 * facebook#35884 * facebook#35883 * facebook#35882 * facebook#35881 * facebook#35880 * facebook#35879 * facebook#35878 * facebook#35877 * facebook#35876 * facebook#35875 * __->__ facebook#35874
…rs on env (facebook#35875) Update 9 validation passes to record errors directly on fn.env instead of returning Result<void, CompilerError>: - validateHooksUsage - validateNoCapitalizedCalls (also changed throwInvalidReact to recordError) - validateUseMemo - dropManualMemoization - validateNoRefAccessInRender - validateNoSetStateInRender - validateNoImpureFunctionsInRender - validateNoFreezingKnownMutableFunctions - validateExhaustiveDependencies Each pass now calls fn.env.recordErrors() instead of returning errors.asResult(). Pipeline.ts call sites updated to remove tryRecord() wrappers and .unwrap(). --- [//]: # (BEGIN SAPLING FOOTER) Stack created with [Sapling](https://sapling-scm.com). Best reviewed with [ReviewStack](https://reviewstack.dev/facebook/react/pull/35875). * facebook#35888 * facebook#35884 * facebook#35883 * facebook#35882 * facebook#35881 * facebook#35880 * facebook#35879 * facebook#35878 * facebook#35877 * facebook#35876 * __->__ facebook#35875
… tolerance (facebook#35876) Update remaining validation passes to record errors on env: - validateMemoizedEffectDependencies - validatePreservedManualMemoization - validateSourceLocations (added env parameter) - validateContextVariableLValues (changed throwTodo to recordError) - validateLocalsNotReassignedAfterRender (changed throw to recordError) - validateNoDerivedComputationsInEffects (changed throw to recordError) Update inference passes: - inferMutationAliasingEffects: return void, errors on env - inferMutationAliasingRanges: return Array<AliasingEffect> directly, errors on env Update codegen: - codegenFunction: return CodegenFunction directly, errors on env - codegenReactiveFunction: same pattern Update Pipeline.ts to call all passes directly without tryRecord/unwrap. Also update AnalyseFunctions.ts which called inferMutationAliasingRanges. --- [//]: # (BEGIN SAPLING FOOTER) Stack created with [Sapling](https://sapling-scm.com). Best reviewed with [ReviewStack](https://reviewstack.dev/facebook/react/pull/35876). * facebook#35888 * facebook#35884 * facebook#35883 * facebook#35882 * facebook#35881 * facebook#35880 * facebook#35879 * facebook#35878 * facebook#35877 * __->__ facebook#35876
…ebook#35877) Add test fixture demonstrating fault tolerance: the compiler now reports both a mutation error and a ref access error in the same function, where previously only one would be reported before bailing out. Update plan doc to mark all phases as complete. --- [//]: # (BEGIN SAPLING FOOTER) Stack created with [Sapling](https://sapling-scm.com). Best reviewed with [ReviewStack](https://reviewstack.dev/facebook/react/pull/35877). * facebook#35888 * facebook#35884 * facebook#35883 * facebook#35882 * facebook#35881 * facebook#35880 * facebook#35879 * facebook#35878 * __->__ facebook#35877
…#35878) --- [//]: # (BEGIN SAPLING FOOTER) Stack created with [Sapling](https://sapling-scm.com). Best reviewed with [ReviewStack](https://reviewstack.dev/facebook/react/pull/35878). * facebook#35888 * facebook#35884 * facebook#35883 * facebook#35882 * facebook#35881 * facebook#35880 * facebook#35879 * __->__ facebook#35878
--- [//]: # (BEGIN SAPLING FOOTER) Stack created with [Sapling](https://sapling-scm.com). Best reviewed with [ReviewStack](https://reviewstack.dev/facebook/react/pull/35879). * facebook#35888 * facebook#35884 * facebook#35883 * facebook#35882 * facebook#35881 * facebook#35880 * __->__ facebook#35879
…ng (facebook#35880) --- [//]: # (BEGIN SAPLING FOOTER) Stack created with [Sapling](https://sapling-scm.com). Best reviewed with [ReviewStack](https://reviewstack.dev/facebook/react/pull/35880). * facebook#35888 * facebook#35884 * facebook#35883 * facebook#35882 * facebook#35881 * __->__ facebook#35880
…ing throws (facebook#35881) Remove `tryRecord()` from the compilation pipeline now that all passes record errors directly via `env.recordError()` / `env.recordErrors()`. A single catch-all try/catch in Program.ts provides the safety net for any pass that incorrectly throws instead of recording. Key changes: - Remove all ~64 `env.tryRecord()` wrappers in Pipeline.ts - Delete `tryRecord()` method from Environment.ts - Add `CompileUnexpectedThrow` logger event so thrown errors are detectable - Log `CompileUnexpectedThrow` in Program.ts catch-all for non-invariant throws - Fail snap tests on `CompileUnexpectedThrow` to surface pass bugs in dev - Convert throwTodo/throwDiagnostic calls in HIRBuilder (fbt, this), CodegenReactiveFunction (for-in/for-of), and BuildReactiveFunction to record errors or use invariants as appropriate - Remove try/catch from BuildHIR's lower() since inner throws are now recorded - CollectOptionalChainDependencies: return null instead of throwing on unsupported optional chain patterns (graceful optimization skip) --- [//]: # (BEGIN SAPLING FOOTER) Stack created with [Sapling](https://sapling-scm.com). Best reviewed with [ReviewStack](https://reviewstack.dev/facebook/react/pull/35881). * facebook#35888 * facebook#35884 * facebook#35883 * facebook#35882 * __->__ facebook#35881
…env.recordError() (facebook#35882) Removes unnecessary indirection in 17 compiler passes that previously accumulated errors in a local `CompilerError` instance before flushing them to `env.recordErrors()` at the end of each pass. Errors are now emitted directly via `env.recordError()` as they're discovered. For passes with recursive error-detection patterns (ValidateNoRefAccessInRender, ValidateNoSetStateInRender), the internal accumulator is kept but flushed via individual `recordError()` calls. For InferMutationAliasingRanges, a `shouldRecordErrors` flag preserves the conditional suppression logic. For TransformFire, the throw-based error propagation is replaced with direct recording plus an early-exit check in Pipeline.ts. --- [//]: # (BEGIN SAPLING FOOTER) Stack created with [Sapling](https://sapling-scm.com). Best reviewed with [ReviewStack](https://reviewstack.dev/facebook/react/pull/35882). * facebook#35888 * facebook#35884 * facebook#35883 * __->__ facebook#35882
…ook#35883) Rename `state: Environment` to `env: Environment` in ValidateMemoizedEffectDependencies visitor methods, and `errorState: Environment` to `env: Environment` in ValidatePreservedManualMemoization's validateInferredDep. --- [//]: # (BEGIN SAPLING FOOTER) Stack created with [Sapling](https://sapling-scm.com). Best reviewed with [ReviewStack](https://reviewstack.dev/facebook/react/pull/35883). * facebook#35888 * facebook#35884 * __->__ facebook#35883
…acebook#35884) Fix the transformFire early-exit in Pipeline.ts to only trigger on new errors from transformFire itself, not pre-existing errors from earlier passes. The previous `env.hasErrors()` check was too broad — it would early-exit on validation errors that existed before transformFire ran. Also add missing blank line in CodegenReactiveFunction.ts Context class, and fix formatting in ValidateMemoizedEffectDependencies.ts. --- [//]: # (BEGIN SAPLING FOOTER) Stack created with [Sapling](https://sapling-scm.com). Best reviewed with [ReviewStack](https://reviewstack.dev/facebook/react/pull/35884). * facebook#35888 * __->__ facebook#35884
…doc (facebook#35888) Add concise fault tolerance documentation to CLAUDE.md and the passes README covering error accumulation, tryRecord wrapping, and the distinction between validation vs infrastructure passes. Remove the detailed planning document now that the work is complete.
## Summary For apps that use AMD, we need to actually `require()` the ReactDevToolsBackend and load it from the AMD module cache. This adds a check for the case where the `ReactDevToolsBackend` isn't defined globally, and so we load it with `require()`. ## How did you test this change? Tested through facebook#35886
… different host/port/path (facebook#35886) ## Summary This enables routing the React Dev Tools through a remote server by being able to specify host, port, and path for the client to connect to. Basically allowing the React Dev Tools server to have the client connect elsewhere. This setups a `clientOptions` which can be set up through environment variables when starting the React Dev Tools server. This change shouldn't affect the traditional usage for React Dev Tools. EDIT: the additional change was moved to another PR ## How did you test this change? Run React DevTools with ``` $ REACT_DEVTOOLS_CLIENT_HOST=<MY_HOST> REACT_DEVTOOLS_CLIENT_PORT=443 REACT_DEVTOOLS_CLIENT_USE_HTTPS=true REACT_DEVTOOLS_PATH=/__react_devtools__/ yarn start ``` Confirm that my application connects to the local React Dev Tools server/instance/electron app through my remote server.
…ok#35893) If a function is known to freeze its inputs, and captures refs, then we can safely assume those refs are not mutated during render. An example is React Native's PanResponder, which is designed for use in interaction handling. Calling `PanResponder.create()` creates an object that shouldn't be interacted with at render time, so we can treat it as freezing its arguments, returning a frozen value, and not accessing any refs in the callbacks passed to it. ValidateNoRefAccessInRender is updated accordingly - if we see a Freeze <place> and ImmutableCapture <place> for the same place in the same instruction, we know that it's not being mutated. Note that this is a pretty targeted fix. One weakness is that we may not always emit a Freeze effect if a value is already frozen, which could cause this optimization not to kick in. The worst case there is that you'd just get a ref access in render error though, not miscompilation. And we could always choose to always emit Freeze effects, even for frozen values, just to retain the information for validations like this.
## Summary This flag enables React's integration with the browser [Trusted Types API](https://developer.mozilla.org/en-US/docs/Web/API/Trusted_Types_API). The Trusted Types API is a browser security feature that helps prevent DOM-based XSS attacks. When a site enables Trusted Types enforcement via `Content-Security-Policy: require-trusted-types-for 'script'`, the browser requires that values passed to DOM injection sinks (like `innerHTML`) are typed objects (`TrustedHTML`, `TrustedScript`, `TrustedScriptURL`) created through developer-defined sanitization policies, rather than raw strings. ### What changed Previously, React always coerced values to strings (via `'' + value`) before passing them to DOM APIs like `setAttribute` and `innerHTML`. This broke Trusted Types because it converted typed objects into plain strings, which the browser would then reject under Trusted Types enforcement. React now passes values directly to DOM APIs without string coercion, preserving Trusted Types objects so the browser can validate them. This applies to `dangerouslySetInnerHTML`, all HTML and SVG attributes, and URL attributes (`href`, `action`, etc). ### Before (broken) Using Trusted Types with something like`dangerouslySetInnerHTML` would throw: ```js const sanitizer = trustedTypes.createPolicy('sanitizer', { createHTML: (input) => DOMPurify.sanitize(input), }); function Comment({text}) { const clean = sanitizer.createHTML(text); // clean is a TrustedHTML object, but React would call '' + clean, // converting it back to a plain string before setting innerHTML. // Under Trusted Types enforcement, the browser rejects the string: // // TypeError: Failed to set 'innerHTML' on 'Element': // This document requires 'TrustedHTML' assignment. return <div dangerouslySetInnerHTML={{__html: clean}} />; } ``` ### After (works) React now passes the TrustedHTML object directly to the DOM without stringifying it: ```js const policy = trustedTypes.createPolicy('sanitizer', { createHTML: (input) => DOMPurify.sanitize(input), }); function Comment({text}) { // TrustedHTML objects are passed directly to innerHTML return <div dangerouslySetInnerHTML={{__html: policy.createHTML(text)}} />; } function UserProfile({bio}) { // String attribute values also preserve Trusted Types objects return <div data-bio={policy.createHTML(bio)} />; } ``` ## Non-breaking change - Sites using Trusted Types: React no longer breaks Trusted Types enforcement. TrustedHTML and TrustedScriptURL objects passed through React props are forwarded to the DOM without being stringified. - Sites not using Trusted Types: No behavior change. DOM APIs accept both strings and Trusted Types objects, so removing the explicit string coercion is functionally identical.
…ok#35912) ## Summary This fixes the semantics of the `timeStamp` property of events in React Native. Currently, most events just assign `Date.now()` (at the time of creating the event object in JavaScript) as the `timeStamp` property. This is a divergence with Web and most native platforms, that use a monotonic timestamp for the value (on Web, the same timestamp provided by `performance.now()`). Additionally, many native events specify a timestamp in the event data object as `timestamp` and gets ignored by the logic in JS as it only looks at properties named `timeStamp` specifically (camel case). This PR fixes both issues by: 1. Using `performance.now()` instead of `Date.now()` by default (if available). 2. Checking for a `timestamp` property before falling back to the default (apart from `timeStamp`). ## How did you test this change? Added unit tests for verify the new behavior.
## Summary This PR updates the event dispatching logic in React Native to expose the dispatched event in the global scope as done on Web (https://dom.spec.whatwg.org/#concept-event-listener-inner-invoke) and in the new implementation of `EventTarget` in React Native (https://github.com/facebook/react-native/blob/d1b2ddc9cb4f7b4cb795fed197347173ed5c4bfb/packages/react-native/src/private/webapis/dom/events/EventTarget.js#L372). ## How did you test this change? Added unit tests
…and ValidatePreservedManualMemoization (facebook#35917) With the recent changes to make the compiler fault tolerant and always continue through all passes, we can now sometimes report duplicative errors. Specifically, when `ValidateExhaustiveDependencies` finds incorrect deps for a useMemo/useCallback call, `ValidatePreservedManualMemoization` will generally also error for the same block, producing duplicate errors. The exhaustive deps error is strictly more informative, so if we've already reported the earlier error we don't need the later one. This adds a `hasInvalidDeps` flag to StartMemoize that is set when ValidateExhaustiveDependencies produces a diagnostic. ValidatePreservedManualMemoization then skips validation for memo blocks with this flag set.
Co-authored-by: Dmitrii Troitskii <jsleitor@gmail.com>
…k#35918) Been enabled in stable for quite a while, also rolled out at Meta.
…n noBackwardRangeExtension heuristic Track catch handler bindings in AliasingState so the backward-alias walk in mutate() stops at catch parameters. Without this, catch parameters aliased to call results in try blocks incorrectly trigger the effectiveSkipAliases heuristic, preventing backward range extension and causing 'Expected a break target' crashes when try-catch blocks get split across reactive scopes. Fixes 4 compiler crashes (try-catch-try-value-modified-in-catch and variants) and 1 snapshot regression (try-catch-alias-try-values). Updates 8 snapshot expectations for tests where the noBackwardRangeExtension change produces different but functionally correct memoization output. Closes facebook#35902
cc3ca6b to
99d6d02
Compare
Owner
Author
|
Superseded by facebook#35934 |
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 free
to 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
Fixes failing compiler snapshot tests introduced by the
noBackwardRangeExtensionchanges for method call receivers.Problem
The
noBackwardRangeExtensionheuristic inInferMutationAliasingRanges.tswalks backward through alias edges to detect function call results (identified by havingmaybeAliases). However, catch parameters are aliased to call results in try blocks via terminalAliaseffects. This caused the heuristic to incorrectly treat catch parameters as independently-memoizable function call results, preventing backward range extension and causing:Invariant: Expected a break target) when try-catch blocks got split across reactive scopesFix
Track catch handler binding identifiers in
AliasingState.catchParams. During the backward-alias walk inmutate(), stop traversal when a catch parameter is encountered. This prevents the heuristic from walking through catch parameter aliases to reach call results withmaybeAliases.Changes
InferMutationAliasingRanges.ts: AddedcatchParams: Set<Identifier>toAliasingState, populated frommaybe-throwterminal Alias effects, and checked during the backward-alias heuristic walk.expect.mdfiles for tests where thenoBackwardRangeExtensionchange produces different but functionally correct memoization output (all eval outputs remain correct)Tests fixed
try-catch-try-value-modified-in-catch(and propagate-scope-deps-hir-fork variant)try-catch-try-value-modified-in-catch-escaping(and propagate-scope-deps-hir-fork variant)try-catch-alias-try-valuesCloses facebook#35902