Skip to content

[1.x] fix: add xslt polyfill so forum continues to boot on browsers without XSLT#4644

Merged
imorland merged 1 commit into
1.xfrom
im/xslt-polyfill
May 8, 2026
Merged

[1.x] fix: add xslt polyfill so forum continues to boot on browsers without XSLT#4644
imorland merged 1 commit into
1.xfrom
im/xslt-polyfill

Conversation

@imorland

@imorland imorland commented May 8, 2026

Copy link
Copy Markdown
Member

Summary

Backports #4359 to the 1.8 line as a patch (1.8.17). Adds an XSLT polyfill so Flarum continues to work end-to-end on browsers that have removed native XSLT support.

Chrome disabled XSLT by default in the Beta channel from version 145 (Dec 2025) and is removing it from Stable in version 158 (Nov 2026). Firefox has signalled it will follow. Without a polyfill, forum.js fails to initialize in those browsers — s9e/TextFormatter references XSLTProcessor during parser init, throws a ReferenceError, and takes the entire app boot down with it. Concretely this means:

  • The forum doesn't render at all (blank page or broken layout)
  • The Mithril store never finishes registering types — every extension that pushes a payload (tags, links, etc.) throws in the console
  • Composer live preview never gets a chance to run
  • Extensions don't initialize

This is a hard breakage, not a degraded UX, and applies to all users on the affected browser versions — not just those who open the composer. With 1.x EOL set to 31 December 2026, the 1-2 month window where 1.x users would otherwise sit on a broken Chrome stable release justifies shipping a patch fix.

How it works

A small (~200 byte) detector is emitted into the document <head>. It tries new XSLTProcessor(); on success it returns immediately. On failure (browser has removed XSLT) it document.write()s a <script src=\"…/xslt-polyfill/xslt-polyfill.min.js\"> tag. Because document.write of a script tag during HTML parsing inserts it inline, the parser blocks until the polyfill loads — guaranteeing window.XSLTProcessor is in place before forum.js executes.

The polyfill URL is resolved against the flarum-assets disk, so it's correct on installs that serve assets locally and on those backed by a remote bucket / CDN. The polyfill (xslt-polyfill ^1.0.21) is published into the assets disk during assets:publish, alongside its lazily-fetched dist/xslt-wasm.js companion. Browsers with working native XSLT never download either file — only the inline detector.

1.x-specific design choice — no constructor change

The 2.x PR added FilesystemFactory as a constructor argument on Frontend\Document. For a 1.x patch release that's off the table, so the 1.x port resolves it via the container inside makeXsltPolyfillLoader() — the same pattern Frontend\Document already uses for TitleDriverInterface (carrying its own // @todo v2.0 inject as dependency instead comment). No public API changes.

Why this approach (vs. inlining)

The polyfill is large (~510 KB gzipped). Inlining it into forum.js for every visitor — including the majority on browsers with working XSLT — would roughly triple the JS payload on every page load. Lazy-loading via the <head> detector restricts the cost to affected browsers and keeps the artifact cacheable as a separate hashed asset.

Operator note: CORS for remote flarum-assets

Operators serving the flarum-assets disk from a different origin (S3, CDN, etc.) must allow CORS from their forum origin to the assets origin. The polyfill's bootstrap loads via <script src> (not CORS-checked), but its WASM sibling (dist/xslt-wasm.js) is fetched via fetch() from inside the polyfill, which is subject to CORS. Without the right CORS headers on the assets bucket, the WASM fetch fails and the polyfill silently doesn't install. Same requirement that already applies to web fonts and any other cross-origin asset; just worth being explicit since this PR adds a new file that uses fetch.

Temporary measure

The polyfill is a stop-gap until s9e/TextFormatter ships an XSLT-free implementation: s9e/TextFormatter#250. Once that lands, the detector and asset publishing can be removed.

Test plan

  • Unit tests on XsltPolyfill::findSource() and ::version()
  • Integration tests on the document head — loader is emitted, stays under 500 bytes, <\/script> split is in place
  • Integration test on assets:publish — both polyfill files copied with correct relative layout
  • Full core test suite passes (555 integration, 142 unit)
  • Manual: Chrome 148 Beta with XSLT disabled — forum.js boots, store types register, extensions initialize, live preview renders

… XSLT

Backports the 2.x polyfill (#4359) for the 1.8 line. Chrome disabled XSLT
in Beta from 145 (Dec 2025) and Stable from 158 (Nov 2026); without the
polyfill, s9e/TextFormatter's `new XSLTProcessor` at parser-init time
throws a ReferenceError that prevents forum.js from booting on those
browsers.

A ~200-byte detector is emitted into the document <head>. It tries to
construct an XSLTProcessor; on failure it document.write()s a script
tag pointing at the polyfill bundle. document.write of a script tag
during HTML parsing blocks the parser until the polyfill loads, so
window.XSLTProcessor is in place before forum.js runs.

The polyfill is published into the flarum-assets disk by assets:publish
and resolved through the disk's own ->url(), so installs that serve
assets from a remote bucket / CDN get the right URL.

To stay patch-release-safe, the FilesystemFactory is resolved via the
container inside makeXsltPolyfillLoader() rather than added to the
Document constructor — same pattern Document already uses for
TitleDriverInterface.
@imorland imorland added this to the 1.8.17 milestone May 8, 2026
@imorland imorland added dependencies Pull requests that update a dependency file prio/high javascript Pull requests that update Javascript code labels May 8, 2026
@imorland imorland marked this pull request as ready for review May 8, 2026 16:29
@imorland imorland requested a review from a team as a code owner May 8, 2026 16:29
@imorland imorland merged commit 282fb7f into 1.x May 8, 2026
409 checks passed
@imorland imorland deleted the im/xslt-polyfill branch May 8, 2026 16:34
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

dependencies Pull requests that update a dependency file javascript Pull requests that update Javascript code prio/high

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant