Opened 4 weeks ago
Last modified 2 weeks ago
#66100 new defect (bug)
Script Modules and Interactivity API hooks should use global instances
| Reported by: | jonsurrell | Owned by: | |
|---|---|---|---|
| Priority: | normal | Milestone: | 7.2 |
| Component: | Script Loader | Version: | 6.5 |
| Severity: | normal | Keywords: | has-patch has-unit-tests |
| Cc: | Focuses: |
Description
WP_Script_Modules::add_hooks() and WP_Interactivity_API::add_hooks() register their callbacks as array( $this, 'method' ). wp-settings.php calls both on after_setup_theme with the instance that is the global at that moment. The callbacks stay bound to that object.
Both instances live in globals so they can be replaced. r57503 made $wp_script_modules a global for that reason. Once the hooks are registered, replacing the global changes what wp_enqueue_script_module(), wp_interactivity_state(), and wp_interactivity_config() write to, but not what prints.
This is different from the behavior with classic scripts.
This was discovered while working on a fix for #64484 in this PR where updating the script modules global had no impact.
Change History (9)
This ticket was mentioned in PR #13509 on WordPress/wordpress-develop by @jonsurrell.
4 weeks ago
#1
- Keywords has-patch has-unit-tests added
This ticket was mentioned in PR #13510 on WordPress/wordpress-develop by @jonsurrell.
4 weeks ago
#2
Same problem as #13509 for WP_Interactivity_API: add_hooks() and data_wp_router_region_processor() bind callbacks to the instance. After the global is replaced, wp_interactivity_state() writes to the new instance and the filters read the old one.
This adds four procedural functions to interactivity-api.php and registers those instead. Hook names, priorities, and the instance methods are unchanged.
Test: replace the global, set state, apply script_module_data_@wordpress/interactivity. Fails on trunk with empty data. The test file's set_up() now installs its instance as the global; it registered hooks on an instance that was never the global.
Compatibility: Gutenberg lib/interactivity-api.php checks this filter by instance with has_filter() and will add its own filter too. Both set the same strings, so output is unchanged. That shim should be updated or removed.
## Use of AI Tools
AI assistance: Yes
Tool(s): Claude Code
Model(s): Claude Fable 5.1, Claude Opus
Used for: code, test, description.
---
This Pull Request is for code review only. Please keep all other discussion in the Trac ticket. Do not merge this Pull Request. See GitHub Pull Requests for Code Review in the Core Handbook for more details.
🤖 Generated with Claude Code
@jonsurrell commented on PR #13510:
4 weeks ago
#3
Ping @darerodz for review.
@jonsurrell commented on PR #13509:
4 weeks ago
#4
This was motivated by https://github.com/WordPress/wordpress-develop/pull/13507 originally. That work no longer depends on this change so I don't have a pressing need to land this.
However, this is a correctness issue. The change in r57503 does not have the desired impact because if the
I do share the back-compat concerns, but I'm also worried that this is a bug where the global can be modified but that doesn't actually do anything.
@westonruter commented on PR #13509:
4 weeks ago
#5
The change in r57503 does not have the desired impact because if the
Because of the what?
@jonsurrell commented on PR #13509:
4 weeks ago
#6
Sorry, I've corrected the updated comment. In short, the global value can be replaced but it doesn't change relevant behavior because script module hooks are registered with whatever instance was used at the after_setup_theme action that registers the hooks.
@jonsurrell commented on PR #13509:
4 weeks ago
#7
There are a number of alternatives I've been considering, none of which I like. For example, the hook methods could perform the expected action if it's the global instance, or invoke the global instance otherwise. This seems like it would address back-compat _and_ the problem of not running the actions on the new global, but it also seems messy and surprising.
@westonruter commented on PR #13509:
3 weeks ago
#8
In short, the global value can be replaced but it doesn't change relevant behavior because script module hooks are registered with whatever instance was used at the
after_setup_themeaction that registers the hooks.
Is replacing global variables like this something that is a common occurrence. It happens all the time in unit tests, but in theme/plugin code I would think that such globals are almost always left alone.
![(please configure the [header_logo] section in trac.ini)](/chrome/site/your_project_logo.png)
WP_Script_Modules::add_hooks()registersarray( $this, 'method' ), so the print callbacks are bound to the instance that was the global onafter_setup_theme. Replacing$wp_script_moduleslater changes what enqueues but not what prints. Scripts and styles use procedural callbacks that read the global at run time.This adds procedural print functions to
script-modules.phpand registers those instead. Hook names, priorities, and the instance methods are unchanged.Test: register the hooks, replace the global, enqueue a module, fire
admin_print_footer_scripts. Fails on trunk with empty output.Compatibility:
remove_action()with the instance callback no longer matches. AMP does this inincludes/class-amp-theme-support.php.## Use of AI Tools
AI assistance: Yes
Tool(s): Claude Code
Model(s): Claude Fable 5.1, Claude Opus
Used for: code, test, description.
---
This Pull Request is for code review only. Please keep all other discussion in the Trac ticket. Do not merge this Pull Request. See GitHub Pull Requests for Code Review in the Core Handbook for more details.
🤖 Generated with Claude Code