[compiler] Allow ref access in PerformanceObserver / ReportingObserve…
GitHub Commits - Example: React

[compiler] Allow ref access in PerformanceObserver / ReportingObserve…

Summary

new PerformanceObserver(cb) and new ReportingObserver(cb) are compiled with a false positive when the callback touches a ref:

Error: Cannot access refs during render
4 | return new PerformanceObserver(() => {
  |^^^^^^^^^^^^^^
Passing a ref to a function may read its value during render

Both constructors only retain the callback and invoke it asynchronously once the observation fires - never during render - so reading (or writing) a ref from the callback is safe.

IntersectionObserver (#37764) and ResizeObserver / MutationObserver (#37895) are already modelled exactly this way; these two were just missed and fall back to the unknown-constructor default, whose Freeze on the callback trips ValidateNoRefAccessInRender. This is the same class of fix as #37895, which is now on main.

Fix

Add both to TYPED_GLOBALS (TypeScript) and build_typed_globals (Rust) using the same signature shape as the existing observers:

Global Constructor signature
PerformanceObserver (callback) → [Freeze]
ReportingObserver (callback, options) → [Freeze, Read]

ReportingObserver's second argument is a genuine constructor argument (unlike the observers whose options belong to observe()), so it is read rather than retained. Both backends are updated so TS and Rust stay in parity.

Tests

Four new fixtures:

  • allow-ref-access-in-performance-observer.ts
  • allow-ref-access-in-reporting-observer.ts

Both fail before the change with Cannot access refs during render and compile to memoized constructors after it.

  • error.invalid-mutate-hook-value-in-performance-observer.js
  • error.invalid-mutate-hook-value-in-reporting-observer.js

Negative controls proving Freeze is not weakened: mutating a useMemo value inside the callback still reports `entries` cannot be modified.

Validation run locally:

  • Full fixture suite (1840 fixtures): 25 changed / 3 failed - identical to the pre-existing baseline (fbt/*, debugger*), no new diffs.
  • tsc --noEmit, eslint src, prettier check-changed all clean.
  • Rust side mirrors the TS change 1:1 but was not compiled locally (no toolchain in this environment); relying on the babel-plugin-react-compiler-rust CI job.

Co-authored-by: zhoubiao188 zh*********@users.noreply.github.com

Repository navigation

Commit c050dbd authored [compiler] Allow ref access in PerformanceObserver / ReportingObserver callbacks (#37996)

Summary

new PerformanceObserver(cb) and new ReportingObserver(cb) are compiled with a false positive when the callback touches a ref:

Error: Cannot access refs during render
4 | return new PerformanceObserver(() => {
  | ^^^^^^^^^^^^^^
Passing a ref to a function may read its value during render

Both constructors only retain the callback and invoke it asynchronously once the observation fires - never during render - so reading (or writing) a ref from the callback is safe.

IntersectionObserver (#37764) and ResizeObserver / MutationObserver (#37895) are already modelled exactly this way; these two were just missed and fall back to the unknown-constructor default, whose Freeze on the callback trips ValidateNoRefAccessInRender. This is the same class of fix as #37895, which is now on main.

Fix

Add both to TYPED_GLOBALS (TypeScript) and build_typed_globals (Rust) using the same signature shape as the existing observers:

Global Constructor signature
PerformanceObserver (callback) → [Freeze]
ReportingObserver (callback, options) → [Freeze, Read]

ReportingObserver's second argument is a genuine constructor argument (unlike the observers whose options belong to observe()), so it is read rather than retained. Both backends are updated so TS and Rust stay in parity.

Tests

Four new fixtures:

  • allow-ref-access-in-performance-observer.ts
  • allow-ref-access-in-reporting-observer.ts

Both fail before the change with Cannot access refs during render and compile to memoized constructors after it.

  • error.invalid-mutate-hook-value-in-performance-observer.js
  • error.invalid-mutate-hook-value-in-reporting-observer.js

Negative controls proving Freeze is not weakened: mutating a useMemo value inside the callback still reports `entries` cannot be modified.

Validation run locally:

  • Full fixture suite (1840 fixtures): 25 changed / 3 failed - identical to the pre-existing baseline (fbt/*, debugger*), no new diffs.
  • tsc --noEmit, eslint src, prettier check-changed all clean.
  • Rust side mirrors the TS change 1:1 but was not compiled locally (no toolchain in this environment); relying on the babel-plugin-react-compiler-rust CI job.

Co-authored-by: zhoubiao188 1 parent 9ca7a27 commit c050dbd 10 files changed Lines changed: 282 additions & 0 deletions File tree - compiler - crates/react_compiler_hir/src - packages/babel-plugin-react-compiler/src - HIR - tests/fixtures/compiler | Original file line number | Diff line number | Diff line change | | |---|---|---|---| | ||| 2385 | 2385 | | | 2386 | 2386 | | | 2387 | 2387 | | | | 2388 | + | | | 2389 | + | | | 2390 | + | | | 2391 | + | | | 2392 | + | | | 2393 | + | | | 2394 | + | | | 2395 | + | | | 2396 | + | | | 2397 | + | | | 2398 | + | | | 2399 | + | | | 2400 | + | | | 2401 | + | | | 2402 | + | | | 2403 | + | | | 2404 | + | | | 2405 | + | | | 2406 | + | | | 2407 | + | | | 2408 | + | | | 2409 | + | | | 2410 | + | | | 2411 | + | | | 2412 | + | | | 2413 | + | | | 2414 | + | | | 2415 | + | | | 2416 | + | | | 2417 | + | | | 2418 | + | | | 2419 | + | | | 2420 | + | | | 2421 | + | | | 2422 | + | | | 2423 | + | | | 2424 | + | | | 2425 | + | | | 2426 | + | | | 2427 | + | | 2388 | 2428 | | | 2389 | 2429 | | | 2390 | 2430 | | | | | Original file line number | Diff line number | Diff line change | | |---|---|---|---| | ||| 693 | 693 | | | 694 | 694 | | | 695 | 695 | | | | 696 | + | | | 697 | + | | | 698 | + | | | 699 | + | | | 700 | + | | | 701 | + | | | 702 | + | | | 703 | + | | | 704 | + | | | 705 | + | | | 706 | + | | | 707 | + | | | 708 | + | | | 709 | + | | | 710 | + | | | 711 | + | | | 712 | + | | | 713 | + | | | 714 | + | | | 715 | + | | | 716 | + | | | 717 | + | | | 718 | + | | | 719 | + | | | 720 | + | | | 721 | + | | | 722 | + | | | 723 | + | | | 724 | + | | | 725 | + | | | 726 | + | | | 727 | + | | | 728 | + | | | 729 | + | | | 730 | + | | | 731 | + | | | 732 | + | | | 733 | + | | 696 | 734 | | | 697 | 735 | | | 698 | 736 | | | | | Original file line number | Diff line number | Diff line change | | |---|---|---|---| | ||| | 1 | + | | | 2 | + | | | 3 | + | | | 4 | + | | | 5 | + | | | 6 | + | | | 7 | + | | | 8 | + | | | 9 | + | | | 10 | + | | | 11 | + | | | 12 | + | | | 13 | + | | | 14 | + | | | 15 | + | | | 16 | + | | | 17 | + | | | 18 | + | | | 19 | + | | | 20 | + | | | 21 | + | | | 22 | + | | | 23 | + | | | 24 | + | | | 25 | + | | | 26 | + | | | 27 | + | | | 28 | + | | | 29 | + | | | 30 | + | | | 31 | + | | | 32 | + | | | 33 | + | | | 34 | + | | | 35 | + | | | 36 | + | | | 37 | + | | | 38 | + | | | 39 | + | | | 40 | + | | | 41 | + | | Original file line number | Diff line number | Diff line change | | |---|---|---|---| | ||| | 1 | + | | | 2 | + | | | 3 | + | | | 4 | + | | | 5 | + | | | 6 | + | | | 7 | + | | | 8 | + | | | 9 | + | | Original file line number | Diff line number | Diff line change | | |---|---|---|---| | ||| | 1 | + | | | 2 | + | | | 3 | + | | | 4 | + | | | 5 | + | | | 6 | + | | | 7 | + | | | 8 | + | | | 9 | + | | | 10 | + | | | 11 | + | | | 12 | + | | | 13 | + | | | 14 | + | | | 15 | + | | | 16 | + | | | 17 | + | | | 18 | + | | | 19 | + | | | 20 | + | | | 21 | + | | | 22 | + | | | 23 | + | | | 24 | + | | | 25 | + | | | 26 | + | | | 27 | + | | | 28 | + | | | 29 | + | | | 30 | + | | | 31 | + | | | 32 | + | | | 33 | + | | | 34 | + | | | 35 | + | | | 36 | + | | | 37 | + | | | 38 | + | | | 39 | + | | | 40 | + | | | 41 | + | | | 42 | + | | | 43 | + | | | 44 | + | | | 45 | + | | | 46 | + | | | 47 | + | | | 48 | + | | Original file line number | Diff line number | Diff line change | | |---|---|---|---| | ||| | 1 | + | | | 2 | + | | | 3 | + | | | 4 | + | | | 5 | + | | | 6 | + | | | 7 | + | | | 8 | + | | | 9 | + | | | 10 | + | | | 11 | + | | | 12 | + | | Original file line number | Diff line number | Diff line change | | |---|---|---|---| | ||| | 1 | + | | | 2 | + | | | 3 | + | | | 4 | + | | | 5 | + | | | 6 | + | | | 7 | + | | | 8 | + | | | 9 | + | | | 10 | + | | | 11 | + | | | 12 | + | | | 13 | + | | | 14 | + | | | 15 | + | | | 16 | + | | | 17 | + | | | 18 | + | | | 19 | + | | | 20 | + | | | 21 | + | | | 22 | + | | | 23 | + | | | 24 | + | | | 25 | + | | | 26 | + | | | 27 | + | | | 28 | + | | | 29 | + | | | 30 | + | | | 31 | + | | | 32 | + | | | 33 | + | | | 34 | + | | | 35 | + | | | 36 | + | | Original file line number | Diff line number | Diff line change | | |---|---|---|---| | ||| | 1 | + | | | 2 | + | | | 3 | + | | | 4 | + | | | 5 | + | | | 6 | + | | | 7 | + | | | 8 | + | | Original file line number | Diff line number | Diff line change | | |---|---|---|---| | ||| | 1 | + | | | 2 | + | | | 3 | + | | | 4 | + | | | 5 | + | | | 6 | + | | | 7 | + | | | 8 | + | | | 9 | + | | | 10 | + | | | 11 | + | | | 12 | + | | | 13 | + | | | 14 | + | | | 15 | + | | | 16 | + | | | 17 | + | | | 18 | + | | | 19 | + | | | 20 | + | | | 21 | + | | | 22 | + | | | 23 | + | | | 24 | + | | | 25 | + | | | 26 | + | | | 27 | + | | | 28 | + | | | 29 | + | | | 30 | + | | | 31 | + | | | 32 | + | | | 33 | + | | | 34 | + | | | 35 | + | | | 36 | + | | | 37 | + | | | 38 | + | | | 39 | + | | Original file line number | Diff line number | Diff line change | | |---|---|---|---| | ||| | 1 | + | | | 2 | + | | | 3 | + | | | 4 | + | | | 5 | + | | | 6 | + | | | 7 | + | | | 8 | + | | | 9 | + | | | 10 | + | | | 11 | + | 0 commit comments

Comments

No comments yet. Start the discussion.