Skip to content

test: Wait for native view lifecycle completion - #1603

Draft
mrousavy wants to merge 1 commit into
mainfrom
fix/harness-view-lifecycle
Draft

test: Wait for native view lifecycle completion#1603
mrousavy wants to merge 1 commit into
mainfrom
fix/harness-view-lifecycle

Conversation

@mrousavy

@mrousavy mrousavy commented Sep 5, 2026

Copy link
Copy Markdown
Member

Harness rerender completion does not establish that Fabric has finished applying native props or recycling a removed view. The tests could therefore read old setter or lifecycle counts, particularly under sanitizer scheduling overhead.

Wait for changed hybridRef callbacks after prop updates and for the exact drop/recycle counts after removal. Publish lifecycle counts across the UI and JS threads using Android atomics and an iOS lock; publish recycle completion after resetting native state. This extracts only the view lifecycle changes from #1530 and uses Foundation's existing NSLock.withLock instead of custom locking helpers.

Validation:

  • Workspace packages build; example TypeScript and targeted ESLint pass.
  • Swift format lint and Kotlin lint pass. NSLock.withLock type-checks against the iOS 15 simulator target.
  • Confirmed in generated native view bindings that prop setters run before the changed hybridRef callback.
  • git diff --check passes. Fresh native builds and Harness tests run on this PR; earlier full Android validation is recorded in Stabilize Android Harness ASan and view lifecycle tests #1530.

@vercel

vercel Bot commented Sep 5, 2026

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

1 Skipped Deployment
Project Deployment Actions Updated
nitro-docs Skipped Skipped Sep 5, 2026 1:02pm UTC

Request Review

@github-actions

github-actions Bot commented Sep 5, 2026

Copy link
Copy Markdown

Performance Report

⚠️ Advisory: Results do not fail this PR while the baseline is being calibrated.

iOS

Benchmark Before After Difference
Swift bounce(4 KiB) 529.4 ns 451.1 ns 🟢 -14.78% faster
Swift copy(1 MiB) 94.21 µs 107.81 µs 🔴 +14.43% slower
All Benchmarks
Benchmark Before After Difference
JavaScript addNumbers() 33.1 ns 35.2 ns 🟡 +6.13% slower (noisy)
C++ bounce(1 MiB) 391.9 ns 391.3 ns 🟡 -0.17% faster (noisy)
C++ bounce(4 KiB) 433.6 ns 383.7 ns 🟡 -11.5% faster (noisy)
C++ copy(1 MiB) 100.51 µs 89.07 µs 🟡 -11.38% faster (noisy)
C++ copy(4 KiB) 1.47 µs 1.51 µs 🟡 +2.19% slower (noisy)
C++ large array (1,024) 58.53 µs 58.06 µs 🟡 -0.8% faster (noisy)
C++ small array (16) 1.11 µs 1.21 µs 🟡 +8.77% slower (noisy)
C++ synchronousCallback() 335.6 ns 339.7 ns 🟡 +1.25% slower (noisy)
C++ create() 577.8 ns 622.6 ns 🟡 +7.77% slower (noisy)
C++ returnExisting() 287.5 ns 283.9 ns 🟡 -1.27% faster (noisy)
C++ typed map (8 entries) 2.27 µs 2.23 µs 🟡 -1.52% faster (noisy)
C++ optional trailing string 222.0 ns 224.7 ns 🟡 +1.22% slower (noisy)
C++ addNumbers() 122.8 ns 126.1 ns 🟡 +2.64% slower (noisy)
C++ simpleFunc() 103.4 ns 108.1 ns 🟡 +4.58% slower (noisy)
C++ immediatePromise() 1.34 µs 1.28 µs ℹ️ -4.64% faster (advisory)
C++ number property get/set 194.3 ns 200.1 ns 🟡 +2.99% slower (noisy)
C++ short ASCII string 193.8 ns 195.1 ns 🟡 +0.67% slower (noisy)
C++ Unicode string 430.8 ns 474.0 ns 🟡 +10.03% slower (noisy)
C++ nested Car struct 2.99 µs 3.04 µs 🟡 +1.53% slower (noisy)
C++ number | string variant 199.1 ns 189.3 ns 🟡 -4.95% faster (noisy)
Swift bounce(1 MiB) 471.9 ns 512.3 ns 🟡 +8.57% slower (noisy)
Swift copy(4 KiB) 1.78 µs 1.96 µs 🟡 +10.4% slower (noisy)
Swift large array (1,024) 63.82 µs 69.05 µs 🟡 +8.19% slower (noisy)
Swift small array (16) 1.28 µs 1.53 µs 🟡 +19.11% slower (noisy)
Swift synchronousCallback() 411.7 ns 438.7 ns 🟡 +6.57% slower (noisy)
Swift create() 46.90 µs 36.88 µs 🟡 -21.37% faster (noisy)
Swift returnExisting() 444.2 ns 412.3 ns 🟡 -7.17% faster (noisy)
Swift typed map (8 entries) 3.27 µs 3.37 µs 🟡 +3.25% slower (noisy)
Swift optional trailing string 253.0 ns 238.8 ns 🟡 -5.63% faster (noisy)
Swift addNumbers() 118.7 ns 133.2 ns 🟡 +12.25% slower (noisy)
Swift simpleFunc() 102.2 ns 102.3 ns 🟡 +0.11% slower (noisy)
Swift immediatePromise() 2.35 µs 2.26 µs ℹ️ -4.07% faster (advisory)
Swift number property get/set 242.0 ns 259.6 ns 🟡 +7.28% slower (noisy)
Swift short ASCII string 258.2 ns 264.1 ns 🟡 +2.31% slower (noisy)
Swift Unicode string 560.3 ns 585.5 ns 🟡 +4.51% slower (noisy)
Swift nested Car struct 3.20 µs 3.17 µs 🟡 -0.9% faster (noisy)
Swift number | string variant 352.5 ns 353.2 ns 🟡 +0.19% slower (noisy)
TurboModule addNumbers() 1.36 µs 1.56 µs 🟡 +14.78% slower (noisy)

Android

Performance is unchanged! 😎

All Benchmarks
Benchmark Before After Difference
JavaScript addNumbers() 31.4 ns 31.5 ns ⚪ ~0.31% unchanged
C++ bounce(1 MiB) 747.5 ns 752.1 ns ⚪ ~0.61% unchanged
C++ bounce(4 KiB) 748.2 ns 743.3 ns 🟡 -0.65% faster (noisy)
C++ copy(1 MiB) 46.20 µs 46.52 µs ⚪ ~0.69% unchanged
C++ copy(4 KiB) 1.49 µs 1.48 µs ⚪ ~0.7% unchanged
C++ large array (1,024) 57.75 µs 57.72 µs ⚪ ~0.05% unchanged
C++ small array (16) 1.27 µs 1.24 µs ⚪ ~1.99% unchanged
C++ synchronousCallback() 538.7 ns 537.9 ns 🟡 -0.15% faster (noisy)
C++ create() 989.8 ns 1.01 µs ⚪ ~2.33% unchanged
C++ returnExisting() 332.6 ns 332.5 ns ⚪ ~0.02% unchanged
C++ typed map (8 entries) 2.73 µs 2.75 µs ⚪ ~0.61% unchanged
C++ optional trailing string 230.8 ns 233.6 ns ⚪ ~1.21% unchanged
C++ addNumbers() 134.7 ns 133.4 ns ⚪ ~0.94% unchanged
C++ simpleFunc() 112.8 ns 112.8 ns ⚪ ~0.06% unchanged
C++ immediatePromise() 1.21 µs 1.20 µs ℹ️ -0.98% faster (advisory)
C++ number property get/set 226.9 ns 229.1 ns ⚪ ~0.94% unchanged
C++ short ASCII string 215.0 ns 215.6 ns ⚪ ~0.27% unchanged
C++ Unicode string 424.3 ns 424.4 ns ⚪ ~0.05% unchanged
C++ nested Car struct 3.46 µs 3.44 µs ⚪ ~0.59% unchanged
C++ number | string variant 206.8 ns 207.9 ns ⚪ ~0.53% unchanged
Kotlin bounce(1 MiB) 1.88 µs 1.87 µs 🟡 -0.45% faster (noisy)
Kotlin bounce(4 KiB) 1.87 µs 1.88 µs 🟡 +0.36% slower (noisy)
Kotlin copy(1 MiB) 478.99 µs 477.90 µs ⚪ ~0.23% unchanged
Kotlin copy(4 KiB) 9.35 µs 9.18 µs ⚪ ~1.79% unchanged
Kotlin large array (1,024) 69.81 µs 70.42 µs ⚪ ~0.88% unchanged
Kotlin small array (16) 1.73 µs 1.75 µs ⚪ ~0.89% unchanged
Kotlin synchronousCallback() 1.78 µs 1.81 µs 🟡 +2.06% slower (noisy)
Kotlin create() 2.79 µs 2.73 µs ⚪ ~2.16% unchanged
Kotlin returnExisting() 953.1 ns 946.4 ns ⚪ ~0.7% unchanged
Kotlin typed map (8 entries) 12.02 µs 11.92 µs ⚪ ~0.79% unchanged
Kotlin optional trailing string 513.0 ns 509.0 ns ⚪ ~0.79% unchanged
Kotlin addNumbers() 185.1 ns 185.0 ns ⚪ ~0.03% unchanged
Kotlin simpleFunc() 155.2 ns 152.6 ns ⚪ ~1.69% unchanged
Kotlin immediatePromise() 3.66 µs 3.69 µs ℹ️ +0.82% slower (advisory)
Kotlin number property get/set 369.6 ns 365.6 ns ⚪ ~1.09% unchanged
Kotlin short ASCII string 732.1 ns 731.4 ns ⚪ ~0.1% unchanged
Kotlin Unicode string 1.18 µs 1.17 µs ⚪ ~0.79% unchanged
Kotlin nested Car struct 8.39 µs 8.36 µs ⚪ ~0.3% unchanged
Kotlin number | string variant 658.4 ns 672.8 ns ⚪ ~2.18% unchanged
TurboModule addNumbers() 374.9 ns 372.7 ns ⚪ ~0.58% unchanged

Benchmarking Code Diff fe50d8fc...017e1b95 (view raw output)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant