[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.tsallow-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.jserror.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-changedall 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-rustCI 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.tsallow-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.jserror.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-changedall 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-rustCI 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.