Hooks: Fix pointer over-advance in resort_active_iterations()#11510
Hooks: Fix pointer over-advance in resort_active_iterations()#11510liaisontw wants to merge 1 commit intoWordPress:trunkfrom
Conversation
|
The following accounts have interacted with this PR and/or linked issues. I will continue to update these lists as activity occurs. You can also manually ask me to refresh this list by adding the Core Committers: Use this line as a base for the props when committing in SVN: To understand the WordPress project's expectations around crediting contributors, please review the Contributor Attribution page in the Core Handbook. |
Test using WordPress PlaygroundThe changes in this pull request can previewed and tested using a WordPress Playground instance. WordPress Playground is an experimental project that creates a full WordPress instance entirely within the browser. Some things to be aware of
For more details about these limitations and more, check out the Limitations page in the WordPress Playground documentation. |
cdf86a9 to
6c33a7d
Compare
|
Test code. Put above wp-includes directory. define( 'ABSPATH', dirname( require_once ABSPATH . WPINC . '/plugin.php'; echo "--- Starting Hook Test ---\n"; $executed_priorities = []; // Priority 10 // Priority 50 } // Priority 100 do_action( 'test_hook' ); echo "--- Test Completed ---\n"; if ( ! in_array( 100, $executed_priorities ) ) { |
7ac631b to
3fa890b
Compare
When a callback removes itself during execution and is the only entry at that priority, the internal array pointer is re-positioned by resort_active_iterations(). Before this fix, the pointer ended up at the next priority, but the subsequent next() call in the main apply_filters() loop would then advance it once more, skipping the next priority entirely. Calling prev() ensures the pointer is balanced so the next() call lands correctly on the intended priority. Fixes #64653.
3fa890b to
2565a9a
Compare
|
@liaisontw, I am not sure I follow the logic behind resubmitting my PR. cc @westonruter. |
There was a problem hiding this comment.
Pull request overview
Fixes an iteration-pointer edge case in WP_Hook::resort_active_iterations() where a self-removing callback (and only callback at its priority) could cause the next priority level to be skipped during apply_filters()/do_action() execution.
Changes:
- Adjust
resort_active_iterations()to step the internal array pointer back when the current priority was removed, preventing an extranext()advance. - Add PHPUnit coverage for self-removing callbacks to ensure subsequent priorities still execute.
Reviewed changes
Copilot reviewed 2 out of 2 changed files in this pull request and generated 3 comments.
| File | Description |
|---|---|
src/wp-includes/class-wp-hook.php |
Adjusts iteration pointer handling in resort_active_iterations() to avoid skipping priorities after removal. |
tests/phpunit/tests/hooks/doAction.php |
Adds regression tests for self-removing callbacks at different priority positions. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| //If the current priority was removed, step back so the next() call in the main loop lands correctly. | ||
| if ( false !== current( $iteration ) && current( $iteration ) !== $current ) { |
| $hook->do_action( array() ); | ||
|
|
||
| $this->assertSame( array( 10, 50, 100 ), $log, 'Priority 100 should not be skipped when priority 50 removes itself during iteration.' ); | ||
| } |
|
|
||
|
|
Retest PR from @mrcasual:
When a callback removes itself during execution and is the only entry at that priority, the internal array pointer is re-positioned by resort_active_iterations().
Before this fix, the pointer ended up at the next priority, but the subsequent next() call in the main apply_filters() loop would then advance it once more, skipping the next priority entirely.
Calling prev() ensures the pointer is balanced so the next() call lands correctly on the intended priority.
Fixes #64653.
Trac ticket: https://core.trac.wordpress.org/ticket/64653