Skip to content

catch cancellationException - #908

Draft
brocollie08 wants to merge 4 commits into
mainfrom
renderableasset-outer-cancellation-catch
Draft

catch cancellationException#908
brocollie08 wants to merge 4 commits into
mainfrom
renderableasset-outer-cancellation-catch

Conversation

@brocollie08

@brocollie08 brocollie08 commented Jul 20, 2026

Copy link
Copy Markdown
Contributor

Change Type (required)

Indicate the type of change your pull request is:

  • patch
  • minor
  • major
  • N/A

Does your PR have any documentation updates?

  • Updated docs
  • No Update needed
  • Unable to update docs
📦 Published PR as canary version: 1.0.2--canary.908.40153

Try this version out locally by upgrading relevant packages to 1.0.2--canary.908.40153

@brocollie08

Copy link
Copy Markdown
Contributor Author

/canary

@intuit-svc

intuit-svc commented Jul 20, 2026

Copy link
Copy Markdown
Contributor

Benchmark Results

Comparison against baseline from main. ⚠️ = regression (>10% slower), ✅ = improvement (>5% faster)

core/player ⚠️

Benchmark Current Baseline Change
core/player/src/binding/__tests__/parser.bench.ts > parser benchmarks > Resolving binding: foo.bar 673.99K ops/s 610.74K ops/s +10.4% ✅
core/player/src/binding/__tests__/parser.bench.ts > parser benchmarks > Resolving binding: foo.pets.1.name 435.23K ops/s 398.04K ops/s +9.3% ✅
core/player/src/binding/__tests__/parser.bench.ts > parser benchmarks > Resolving binding: foo.pets.01.name 373.25K ops/s 408.02K ops/s -8.5%
core/player/src/binding/__tests__/parser.bench.ts > parser benchmarks > Resolving binding: foo.pets['01'].name 393.14K ops/s 348.08K ops/s +12.9% ✅
core/player/src/binding/__tests__/parser.bench.ts > parser benchmarks > Resolving binding: foo.pets[01].name 444.70K ops/s 372.99K ops/s +19.2% ✅
core/player/src/binding/__tests__/parser.bench.ts > parser benchmarks > Resolving binding: foo.pets[name = "frodo"].type 250.34K ops/s 189.21K ops/s +32.3% ✅
core/player/src/binding/__tests__/parser.bench.ts > parser benchmarks > Resolving binding: foo.pets["name" = "sprinkles"].type 205.49K ops/s 163.97K ops/s +25.3% ✅
core/player/src/binding/__tests__/parser.bench.ts > parser benchmarks > Resolving binding: foo.pets["isDog" = false].type 293.36K ops/s 207.41K ops/s +41.4% ✅
core/player/src/binding/__tests__/parser.bench.ts > parser benchmarks > Resolving binding: foo.pets["isDog" = true].type 214.91K ops/s 229.88K ops/s -6.5%
core/player/src/binding/__tests__/parser.bench.ts > binding creation benchmarks > Resolving binding: foo.bar 351.56K ops/s 317.08K ops/s +10.9% ✅
core/player/src/binding/__tests__/parser.bench.ts > binding creation benchmarks > Resolving binding: foo.pets.1.name 238.85K ops/s 214.58K ops/s +11.3% ✅
core/player/src/binding/__tests__/parser.bench.ts > binding creation benchmarks > Resolving binding: foo.pets.01.name 248.46K ops/s 256.79K ops/s -3.2%
core/player/src/binding/__tests__/parser.bench.ts > binding creation benchmarks > Resolving binding: foo.pets['01'].name 231.68K ops/s 230.94K ops/s +0.3%
core/player/src/binding/__tests__/parser.bench.ts > binding creation benchmarks > Resolving binding: foo.pets[01].name 327.29K ops/s 218.21K ops/s +50.0% ✅
core/player/src/binding/__tests__/parser.bench.ts > binding creation benchmarks > Resolving binding: foo.pets[name = "frodo"].type 169.85K ops/s 140.25K ops/s +21.1% ✅
core/player/src/binding/__tests__/parser.bench.ts > binding creation benchmarks > Resolving binding: foo.pets["name" = "sprinkles"].type 116.72K ops/s 134.47K ops/s -13.2% ⚠️
core/player/src/binding/__tests__/parser.bench.ts > binding creation benchmarks > Resolving binding: foo.pets["isDog" = false].type 200.04K ops/s 140.21K ops/s +42.7% ✅
core/player/src/binding/__tests__/parser.bench.ts > binding creation benchmarks > Resolving binding: foo.pets["isDog" = true].type 217.25K ops/s 144.43K ops/s +50.4% ✅
core/player/src/expressions/__tests__/performance.bench.ts > Expression Parsing/Execution Benchmark > Parsing: {{foo}} = 1 + 3 (sync) 328.58K ops/s 368.43K ops/s -10.8% ⚠️
core/player/src/expressions/__tests__/performance.bench.ts > Expression Parsing/Execution Benchmark > Parsing: {{foo}} = 1 + 3 (async) 276.28K ops/s 281.47K ops/s -1.8%
core/player/src/expressions/__tests__/performance.bench.ts > Expression Parsing/Execution Benchmark > Parsing: conditional(true, true, false) (sync) 327.63K ops/s 351.49K ops/s -6.8%
core/player/src/expressions/__tests__/performance.bench.ts > Expression Parsing/Execution Benchmark > Parsing: conditional(true, true, false) (async) 256.12K ops/s 274.13K ops/s -6.6%
core/player/src/expressions/__tests__/performance.bench.ts > Expression Parsing/Execution Benchmark > Parsing: {{foo}} = conditional({{bar}} > 0, true, false) (sync) 124.36K ops/s 152.69K ops/s -18.6% ⚠️
core/player/src/expressions/__tests__/performance.bench.ts > Expression Parsing/Execution Benchmark > Parsing: {{foo}} = conditional({{bar}} > 0, true, false) (async) 119.88K ops/s 130.39K ops/s -8.1%
core/player/src/expressions/__tests__/performance.bench.ts > Expression Parsing/Execution Benchmark > Parsing: {{foo}} = conditional(conditional(true = false, false, true), conditional(false = false, true, false), conditional(true = true, false, true)) (sync) 120.96K ops/s 120.50K ops/s +0.4%
core/player/src/expressions/__tests__/performance.bench.ts > Expression Parsing/Execution Benchmark > Parsing: {{foo}} = conditional(conditional(true = false, false, true), conditional(false = false, true, false), conditional(true = true, false, true)) (async) 133.61K ops/s 99.43K ops/s +34.4% ✅
core/player/src/expressions/__tests__/performance.bench.ts > Expression Parsing/Execution Benchmark > Parsing: {{foo}} = await(asyncTestFunction(1)) (sync) N/A N/A N/A
core/player/src/expressions/__tests__/performance.bench.ts > Expression Parsing/Execution Benchmark > Parsing: {{foo}} = await(asyncTestFunction(1)) (async) 214.35K ops/s 202.68K ops/s +5.8% ✅
core/player/src/expressions/__tests__/performance.bench.ts > Expression Parsing/Execution Benchmark > Parsing: {{foo}} = asyncTestFunction(1) (sync) 280.76K ops/s 215.91K ops/s +30.0% ✅
core/player/src/expressions/__tests__/performance.bench.ts > Expression Parsing/Execution Benchmark > Parsing: {{foo}} = asyncTestFunction(1) (async) 202.63K ops/s 201.74K ops/s +0.4%
core/player/src/expressions/__tests__/performance.bench.ts > Expression Parsing/Execution Benchmark > Parsing: asyncTestFunction(1) (sync) 602.70K ops/s 599.57K ops/s +0.5%
core/player/src/expressions/__tests__/performance.bench.ts > Expression Parsing/Execution Benchmark > Parsing: asyncTestFunction(1) (async) 451.40K ops/s 475.01K ops/s -5.0%
core/player/src/expressions/__tests__/performance.bench.ts > Expression Parsing/Execution Benchmark > Parsing: {{foo}} = conditional(!{{bar}} == false, await(asyncTestFunction(1)), false) (sync) 154.29K ops/s 133.73K ops/s +15.4% ✅
core/player/src/expressions/__tests__/performance.bench.ts > Expression Parsing/Execution Benchmark > Parsing: {{foo}} = conditional(!{{bar}} == false, await(asyncTestFunction(1)), false) (async) 163.50K ops/s 132.14K ops/s +23.7% ✅
core/player/src/view/resolver/__tests__/index.bench.ts > resolver benchmarks > initial resolve 446.00 ops/s 372.83 ops/s +19.6% ✅
core/player/src/view/resolver/__tests__/index.bench.ts > resolver benchmarks > Resolving from cache 16.05K ops/s 12.13K ops/s +32.4% ✅
core/player/src/view/resolver/__tests__/index.bench.ts > resolver benchmarks > data changes 1.82K ops/s 1.54K ops/s +18.3% ✅
core/player/src/view/resolver/__tests__/index.bench.ts > resolver benchmarks > data changes slow 521.69 ops/s 458.87 ops/s +13.7% ✅

plugins/async-node/core

Benchmark Current Baseline Change
plugins/async-node/core/src/__tests__/index.bench.ts > async node benchmarks > Resolve Async Node 1 times 12.91K ops/s 8.60K ops/s +50.1% ✅
plugins/async-node/core/src/__tests__/index.bench.ts > async node benchmarks > Resolve Async Node 5 times 12.90K ops/s 8.93K ops/s +44.4% ✅
plugins/async-node/core/src/__tests__/index.bench.ts > async node benchmarks > Resolve Async Node 10 times 9.68K ops/s 7.76K ops/s +24.8% ✅
plugins/async-node/core/src/__tests__/index.bench.ts > async node benchmarks > Resolve Async Node 50 times 3.05K ops/s 2.95K ops/s +3.2%
plugins/async-node/core/src/__tests__/index.bench.ts > async node benchmarks > Resolve Async Node 100 times 1.74K ops/s 1.59K ops/s +9.5% ✅
plugins/async-node/core/src/__tests__/transform.bench.ts > async transform benchmarks > Resolve Async Node 1 times 6.87K ops/s 4.55K ops/s +51.0% ✅
plugins/async-node/core/src/__tests__/transform.bench.ts > async transform benchmarks > Resolve Async Node 5 times 7.06K ops/s 4.96K ops/s +42.3% ✅
plugins/async-node/core/src/__tests__/transform.bench.ts > async transform benchmarks > Resolve Async Node 10 times 7.08K ops/s 3.77K ops/s +87.8% ✅
plugins/async-node/core/src/__tests__/transform.bench.ts > async transform benchmarks > Resolve Async Node 50 times 2.17K ops/s 1.71K ops/s +27.4% ✅
plugins/async-node/core/src/__tests__/transform.bench.ts > async transform benchmarks > Resolve Async Node 100 times 1.57K ops/s 1.10K ops/s +42.4% ✅

react/player ⚠️

Benchmark Current Baseline Change
react/player/src/asset/__tests__/index.bench.tsx > ReactAsset benchmarks > Render asset nested in 1 ReactAssets 624.70 ops/s 615.72 ops/s +1.5%
react/player/src/asset/__tests__/index.bench.tsx > ReactAsset benchmarks > Bubble errors nested in 1 ReactAssets 1.03K ops/s 1.07K ops/s -3.7%
react/player/src/asset/__tests__/index.bench.tsx > ReactAsset benchmarks > Render asset nested in 5 ReactAssets 620.50 ops/s 624.53 ops/s -0.6%
react/player/src/asset/__tests__/index.bench.tsx > ReactAsset benchmarks > Bubble errors nested in 5 ReactAssets 945.69 ops/s 1.08K ops/s -12.2% ⚠️
react/player/src/asset/__tests__/index.bench.tsx > ReactAsset benchmarks > Render asset nested in 10 ReactAssets 639.48 ops/s 622.87 ops/s +2.7%
react/player/src/asset/__tests__/index.bench.tsx > ReactAsset benchmarks > Bubble errors nested in 10 ReactAssets 913.81 ops/s 906.48 ops/s +0.8%
react/player/src/asset/__tests__/index.bench.tsx > ReactAsset benchmarks > Render asset nested in 50 ReactAssets 490.27 ops/s 505.36 ops/s -3.0%
react/player/src/asset/__tests__/index.bench.tsx > ReactAsset benchmarks > Bubble errors nested in 50 ReactAssets 248.27 ops/s 259.45 ops/s -4.3%
react/player/src/asset/__tests__/index.bench.tsx > ReactAsset benchmarks > Render asset nested in 100 ReactAssets 392.92 ops/s 420.63 ops/s -6.6%
react/player/src/asset/__tests__/index.bench.tsx > ReactAsset benchmarks > Bubble errors nested in 100 ReactAssets 112.94 ops/s 124.25 ops/s -9.1%

intuit-svc added a commit to player-ui/player-ui.github.io that referenced this pull request Jul 20, 2026
@intuit-svc

intuit-svc commented Jul 20, 2026

Copy link
Copy Markdown
Contributor

Build Preview

Your PR was deployed by CircleCI #40153 on Wed, 22 Jul 2026 18:54:00 GMT with this version:

1.0.2--canary.908.40153

📖 Docs (View site)

@codecov

codecov Bot commented Jul 20, 2026

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 0.00%. Comparing base (234b749) to head (a0fd330).

Additional details and impacted files
@@     Coverage Diff     @@
##   main   #908   +/-   ##
===========================
===========================

☔ View full report in Codecov by Harness.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

* Fix cancellation swallowed as AssetRenderException in RenderableAsset.render()

render()'s outer catch didn't special-case CancellationException the way
doRender()'s inner catch already does. When a parent rehydrates while an
in-flight inflateChild() render() call for a child asset is still suspended,
the parent's renewHydrationScope() cancellation gets wrapped into
AssetRenderException("Failed to render asset") instead of propagating as-is,
escaping inflateChild()'s unguarded launch and failing the whole flow.

Includes an isolated repro test demonstrating the race and confirming the fix.

* Fix hydration tracker leak when a rehydrate is cancelled mid-flight

RenderableAsset.render()'s rehydrate branch only called
asyncHydrationTrackerPlugin.renderingComplete() from its try/catch
(StaleViewException) bodies, not a finally. If rehydrate(cachedView) throws a
CancellationException instead (e.g. a second rehydrate for the same asset id
cancelling the hydrationScope this one is suspended in), renderingComplete()
is skipped, permanently leaking that asset id in the tracker's pending set.
onHydrationComplete then never fires again for that flow, hanging
IdlingResourcePlugin's waitForIdleSync() until IdlingResourceTimeoutException.

Moved renderingComplete() into a finally block, mirroring doRender()'s
existing correct pattern.

Adds a repro test using an independent sibling asset to isolate the leak
(a later successful render for the SAME asset id would otherwise mask it,
since pending is a plain Set<String> keyed by id).
@brocollie08

Copy link
Copy Markdown
Contributor Author

/canary

@brocollie08

Copy link
Copy Markdown
Contributor Author

/canary

@brocollie08

Copy link
Copy Markdown
Contributor Author

/canary

intuit-svc added a commit to player-ui/player-ui.github.io that referenced this pull request Jul 22, 2026
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.

3 participants