Skip to content

Preserve duplicate triggers while preferring latest equal uptime#87

Merged
pyricau merged 14 commits intomainfrom
sedwards/no-ticket/fix-trigger-forwarding-stack
Apr 2, 2026
Merged

Preserve duplicate triggers while preferring latest equal uptime#87
pyricau merged 14 commits intomainfrom
sedwards/no-ticket/fix-trigger-forwarding-stack

Conversation

@steve-the-edwards
Copy link
Copy Markdown
Contributor

@steve-the-edwards steve-the-edwards commented Apr 1, 2026

Summary

This keeps duplicate trigger instances on the main-thread stack instead of collapsing them, while making stack selection simpler and library-specific.

  • preserve duplicate trigger instances on the stack for nested scopes
  • prefer the most recently pushed trigger when two triggers have the same uptime
  • describe inputEventInteractionTriggers as a filtered stack view that preserves duplicate order
  • revert the unrelated MainThreadMessageSpyTest change from .last() back to .single()
  • convert the touched unit tests to Truth assertions

Testing

  • ./gradlew :papa:testDebugUnitTest --tests 'papa.InteractionTriggerTest' --tests 'papa.MainThreadTriggerStackTest' :papa:compileDebugAndroidTestKotlin :papa:ktlintCheck --console=plain

@steve-the-edwards steve-the-edwards marked this pull request as ready for review April 1, 2026 15:22
steve-the-edwards and others added 2 commits April 1, 2026 12:16
Add API 23 to the existing class-level skip predicate (API 28 was
already skipped for similar reasons). On API 23 the Choreographer
FrameDisplayEventReceiver timing differs from newer APIs, causing
inputEventDispatching_not_in_MainThread_Message to flake: the tap
lands while a FrameDisplayEventReceiver message is still the current
Looper message, so currentMessageAsString is non-null instead of the
expected null.

This is a pre-existing flaky test unrelated to the trigger-forwarding
fix — neither the test file nor MainThreadMessageSpy.kt were changed
by this PR.

Amp-Thread-ID: https://ampcode.com/threads/T-019d49fc-3bb3-71df-b4a6-eab56e473ee8
Co-authored-by: Amp <amp@ampcode.com>
@steve-the-edwards steve-the-edwards force-pushed the sedwards/no-ticket/fix-trigger-forwarding-stack branch from 955748f to 5efe9bf Compare April 1, 2026 18:30
Replace the two-pass forward+reverse scan in earliestInteractionTrigger
with a single reduceOrNull call that prefers the last-pushed trigger on
equal name+uptime ties.

Remove LinkedHashMap and Pair key allocations from
inputEventInteractionTriggers. Duplicates are now handled by in-place
replacement in the ArrayList via indexOfFirst, and the single-element
case just reassigns firstInputEventTrigger.

Co-authored-by: Amp <amp@ampcode.com>
Amp-Thread-ID: https://ampcode.com/threads/T-019d49fc-3bb3-71df-b4a6-eab56e473ee8
@steve-the-edwards steve-the-edwards force-pushed the sedwards/no-ticket/fix-trigger-forwarding-stack branch from 5efe9bf to d41adb4 Compare April 1, 2026 18:33
steve-the-edwards and others added 9 commits April 1, 2026 14:59
Drop the unused InteractionTrigger equals overrides so trigger identity stays consistent with the stack semantics and we no longer advertise value-style equality without a matching hashCode. Update the trigger tests and stack assertions to check identity explicitly.

Amp-Thread-ID: https://ampcode.com/threads/T-019d4a72-a08b-755a-a093-f77c3896b250
Co-authored-by: Amp <amp@ampcode.com>
Expose a narrow internal factory for unit tests that only need an InputEventTrigger payload without wiring window frame tracking. This replaces reflective construction in MainThreadTriggerStackTest so the test no longer depends on Kotlin Duration JVM internals or synthetic constructors.

Amp-Thread-ID: https://ampcode.com/threads/T-019d4a72-a08b-755a-a093-f77c3896b250
Co-authored-by: Amp <amp@ampcode.com>
Add KDoc for the InputEventTrigger test helper and explain the equal-trigger stack assertions in MainThreadTriggerStackTest so the forwarding behavior under test is obvious when reading the file.

Amp-Thread-ID: https://ampcode.com/threads/T-019d4a72-a08b-755a-a093-f77c3896b250
Co-authored-by: Amp <amp@ampcode.com>
Document that inputEventInteractionTriggers is a distinct effective-input projection rather than a raw stack dump, and explain why equal forwarded copies are collapsed to the active instance.

Amp-Thread-ID: https://ampcode.com/threads/T-019d4a72-a08b-755a-a093-f77c3896b250
Co-authored-by: Amp <amp@ampcode.com>
Clarify the deduped input-event trigger view without overstating a broader consumer contract. The KDoc now focuses on the actual behavior from this change: equal forwarded copies can coexist on the raw stack, while this property returns a single representative and prefers the active forwarded copy while it is in scope.

Amp-Thread-ID: https://ampcode.com/threads/T-019d4a72-a08b-755a-a093-f77c3896b250
Co-authored-by: Amp <amp@ampcode.com>
Stop deduplicating inputEventInteractionTriggers so it remains a filtered view of the current stack. Update the stack and instrumentation tests to stop assuming a single representative trigger and instead read the most recently visible input trigger when needed.

Amp-Thread-ID: https://ampcode.com/threads/T-019d4a72-a08b-755a-a093-f77c3896b250
Co-authored-by: Amp <amp@ampcode.com>
Replace the custom fast-path implementation of inputEventInteractionTriggers with the direct filtered-stack form now that we intentionally preserve duplicate forwarded copies. The behavior stays the same while the code becomes much easier to read.

Amp-Thread-ID: https://ampcode.com/threads/T-019d4a72-a08b-755a-a093-f77c3896b250
Co-authored-by: Amp <amp@ampcode.com>
Sync the generated public API after removing the InteractionTrigger equals declarations and implementations.

Amp-Thread-ID: https://ampcode.com/threads/T-019d4a72-a08b-755a-a093-f77c3896b250
Co-authored-by: Amp <amp@ampcode.com>
@steve-the-edwards steve-the-edwards changed the title Preserve equal triggers while preferring forwarded copies Preserve duplicate triggers while preferring latest equal uptime Apr 2, 2026
@pyricau pyricau merged commit e1dad57 into main Apr 2, 2026
17 checks passed
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.

2 participants