Skip to content

Script Loader: Remove obsolete pr attribute from resource hints and allow spec-defined link attributes - #15331

Draft
westonruter wants to merge 6 commits into
WordPress:trunkfrom
westonruter:fix/resource-hints-pr-attribute
Draft

westonruter wants to merge 6 commits into
WordPress:trunkfrom
westonruter:fix/resource-hints-pr-attribute

Conversation

@westonruter

Copy link
Copy Markdown
Member

The pr ("hint probability") attribute allowed by wp_resource_hints() since r38826 was only ever part of the W3C Resource Hints working drafts. No browser implemented it, and it was removed from that spec in w3c/resource-hints#76. The HTML Living Standard, which now defines resource hints, has no such attribute on <link>, so printing it only produces invalid markup.

This PR:

  • Stops printing pr and removes it from the wp_resource_hints filter documentation.
  • Moves the inline allowlist into an $allowed_attributes map from each attribute name to whether it may be printed without a value. Only crossorigin can be valueless.
  • Allows fetchpriority, hreflang, media, referrerpolicy, and title, the remaining <link> attributes the spec permits with dns-prefetch, preconnect, prefetch, and prerender. Of these, fetchpriority most closely fills the role pr was meant to. The other <link> attributes stay disallowed because the spec restricts them to other link types: blocking, color, disabled, imagesizes, imagesrcset, integrity, and sizes.

Behavior changes for valueless attributes:

  • 'crossorigin' => true prints a bare crossorigin instead of crossorigin='1', and false omits it instead of printing crossorigin=''.
  • A list item, as in array( 'crossorigin', 'href' => … ), is printed only when it names an allowed attribute that may be valueless. Previously any string list item was printed as a bare attribute, which let arbitrary attribute names bypass the allowlist.
  • true or false supplied for an attribute that requires a value is skipped instead of being printed as '1' or ''.

Trac ticket: https://core.trac.wordpress.org/ticket/66435

Use of AI Tools

AI assistance: Yes
Tool(s): Claude Code
Model(s): Claude Opus 5.5 (medium effort)
Used for: Researching the status of the pr attribute and the <link> attributes in the HTML spec, implementing the changes and tests, and drafting the Trac ticket and this description, under the direction of the author, who reviewed the result.


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.

westonruter and others added 4 commits November 1, 2026 09:39
The `pr` (hint probability) attribute was only ever part of the W3C
Resource Hints working drafts. No browser implemented it, and it was
removed from that spec in 2018. The HTML Living Standard, which now
defines resource hints, has no such attribute on `<link>`, so printing it
only produces invalid markup.

Remove `pr` from the allowed attributes and from the `wp_resource_hints`
filter documentation. The test keeps passing `pr` to assert that it is
now dropped.

Co-Authored-By: Claude Opus 5.5 (medium effort) <noreply@anthropic.com>
Claude-Code-Session-Id: 7f6d7eea-e6bc-4b05-9181-cad948a21000
Move the inline attribute allowlist in `wp_resource_hints()` up into an
`$allowed_attributes` map, keyed by attribute name, whose value says
whether the attribute may be printed without a value. Of the currently
allowed attributes, only `crossorigin` can be.

This tightens how valueless attributes are handled:

* `'crossorigin' => true` now prints a bare `crossorigin` instead of
  `crossorigin='1'`, and `false` omits it instead of printing
  `crossorigin=''`.
* A list item, as in `array( 'crossorigin', 'href' => … )`, is now
  printed only when it names an allowed attribute which may be valueless.
  Previously any string list item was printed as a bare attribute, which
  let arbitrary attribute names past the allowlist.
* `true` or `false` given for an attribute that requires a value is
  skipped rather than printed as `'1'` or `''`.

Co-Authored-By: Claude Opus 5.5 (medium effort) <noreply@anthropic.com>
Claude-Code-Session-Id: 7f6d7eea-e6bc-4b05-9181-cad948a21000
Add `fetchpriority`, `hreflang`, `media`, `referrerpolicy`, and `title` to
the attributes `wp_resource_hints()` prints. They are the remaining
attributes of the HTML link element which the spec allows with the
dns-prefetch, preconnect, prefetch, and prerender link types. Of these,
`fetchpriority` is the closest successor to the removed `pr` attribute,
as it lets a hint signal how important its fetch is.

The other link attributes stay disallowed, since the spec only permits
them with other link types: `blocking` (stylesheet, expect), `color`
(mask-icon), `disabled` (stylesheet), `imagesizes` and `imagesrcset`
(preload of an image), `integrity` (stylesheet, preload, modulepreload),
and `sizes` (icons).

Co-Authored-By: Claude Opus 5.5 (medium effort) <noreply@anthropic.com>
Claude-Code-Session-Id: 7f6d7eea-e6bc-4b05-9181-cad948a21000
Co-Authored-By: Claude Opus 5.5 (medium effort) <noreply@anthropic.com>
Claude-Code-Session-Id: 7f6d7eea-e6bc-4b05-9181-cad948a21000
@github-actions

github-actions Bot commented Nov 1, 2026

Copy link
Copy Markdown

Test using WordPress Playground

The 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

  • All changes will be lost when closing a tab with a Playground instance.
  • All changes will be lost when refreshing the page.
  • A fresh instance is created each time the link below is clicked.
  • Every time this pull request is updated, a new ZIP file containing all changes is created. If changes are not reflected in the Playground instance,
    it's possible that the most recent build failed, or has not completed. Check the list of workflow runs to be sure.

For more details about these limitations and more, check out the Limitations page in the WordPress Playground documentation.

Test this pull request with WordPress Playground.

@westonruter

Copy link
Copy Markdown
Member Author

🤖 Comment by Claude Opus 5.5 · medium effort

The plugin and theme directories were searched with Veloria for code that this change would affect.

pr attribute: no usage found

  • No plugin or theme passes 'pr' => with a probability value. Case-insensitive matches for 'pr' => turned up only unrelated arrays: Freemius country lists ('PR' => 'Puerto Rico'), public suffix lists, CSS padding options (pt/pr/pb/pl), payment line items, and query args.
  • 'pr' => with a variable value (15 matches across 13 plugins) is likewise unrelated to resource hints.
  • No plugin or theme prints pr= on a hand-written <link rel="dns-prefetch|preconnect|prefetch|prerender"> either.

So dropping pr appears to affect no one.

'crossorigin' => true: output improves

About 850 wp_resource_hints filter callbacks exist (459 across 387 plugins, 787 across 571 themes). Most add a fonts.gstatic.com preconnect using the list-item form from the bundled themes, array( 'href' => …, 'crossorigin' ). That form is unchanged.

A few pass 'crossorigin' => true, which currently prints crossorigin='1':

  • Go (60,000 installs): includes/core.php:524
  • Simple CAPTCHA with Cloudflare Turnstile (200,000 installs): inc/integrations/other/resource-hints.php:27
  • Tiger Elements Forms: src/Form/Widget/Asset_Manager.php:373
  • Ayyash: inc/customizer/class-ayyash-customize.php:189

With this change they print a bare crossorigin instead. Since '1' is an invalid value for a CORS settings attribute, browsers already treat it as anonymous, so fetch behavior is unchanged. Only the markup becomes valid.

Most other 'crossorigin' => true matches (233 across 146 plugins) are wp_kses() allowed-HTML arrays, which are unaffected.

List items other than crossorigin: none found

No hint arrays were found that pass a list item other than crossorigin, such as 'anonymous' or 'use-credentials' without a key. Those will now be dropped. The searches here are line-based, so a list item inside a multi-line array that does not sit on its own line could have been missed.

westonruter and others added 2 commits November 1, 2026 21:38
The resource hint tests compared the printed `<link>` tags as exact
strings, so they also asserted incidental details such as attribute order
and quoting style. Use `assertEqualHTML()` so they assert only that the
markup is equivalent HTML.

Co-Authored-By: Claude Opus 5.5 (medium effort) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Tnky3GYbMqxozZLnF3PvQp
Claude-Code-Session-Id: 7f6d7eea-e6bc-4b05-9181-cad948a21000
Co-Authored-By: Claude Opus 5.5 (medium effort) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Tnky3GYbMqxozZLnF3PvQp
Claude-Code-Session-Id: 7f6d7eea-e6bc-4b05-9181-cad948a21000
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