Skip to content

yesod-core: gate encoding dependency off Windows - #1924

Merged
parsonsmatt merged 4 commits into
masterfrom
mattp/fix-windows-ci
Jun 22, 2026
Merged

parsonsmatt merged 4 commits into
masterfrom
mattp/fix-windows-ci

Conversation

@parsonsmatt

Copy link
Copy Markdown
Collaborator

Problem

The Windows CI jobs for lts-16 and lts-23 have been failing. Both trace to a single dependency: encoding, added in #1894 for typedContentToSnippet's CJK charset decoding.

  • lts-16 (ghc-8.8): encoding → regex-compat → regex-posix, which needs POSIX regex.h — absent in that Windows mingw64 toolchain.
  • lts-23 (ghc-9.8): encoding itself needs system_encoding.h — absent in the clang64 toolchain.

The other Windows configs (lts-18/20/22) happened to build it, so it's a brittle, toolchain-dependent dependency.

Fix

Gate encoding behind if !os(windows) in all three yesod-core stanzas (library, test-routes, tests), each pairing the dependency with a -DWITH_DATA_ENCODING cpp flag so the source guard can never drift from whether the package was linked.

  • TypedContent.hs: the four CJK charset imports and decoder branches are #ifdef-guarded; on Windows those charsets fall through to the existing utf-8-lenient otherwise branch.
  • Content.hs (test): the CJK imports, helpers, and four test cases are guarded the same way.

CJK decoding (GB18030/windows-1251/Shift_JIS/Windows-31J) is fully preserved on Linux/macOS. Only Windows degrades to utf-8-lenient for those four charsets, and only in the debug content-snippet display — actual response serving is untouched.

Verification

  • Linux (flag on): yesod-core builds; tests 374/374 and test-routes 111/111 pass.
  • Windows path (flag off, simulated locally): both TypedContent.hs and the test typecheck cleanly with WITH_DATA_ENCODING undefined, confirming neither references encoding on that path.

🤖 Generated with Claude Code

The `encoding` package (added in #1894 for typedContentToSnippet's CJK
charset decoding) fails to build on Windows: it drags in
regex-compat -> regex-posix (needs POSIX regex.h, missing on the ghc-8.8
mingw64 toolchain) and itself needs system_encoding.h (missing on the
ghc-9.8 clang64 toolchain). This broke the lts-16 and lts-23 Windows CI
jobs.

Gate the dependency behind `if !os(windows)` in all three yesod-core
stanzas, pairing it with a -DWITH_DATA_ENCODING cpp flag so the source
guard always matches whether the package was linked. On Windows the four
CJK charsets (GB18030/windows-1251/Shift_JIS/Windows-31J) fall back to
utf-8-lenient decoding in the content snippet; behavior is unchanged on
all other platforms, where CJK decoding is fully preserved.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@parsonsmatt
parsonsmatt marked this pull request as ready for review June 18, 2026 21:50
parsonsmatt and others added 3 commits June 18, 2026 15:50
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Move all of the WITH_DATA_ENCODING CPP into a new internal module,
Yesod.Core.Internal.ContentCharset, which exposes a CPP-free API:

    lookupExtraCharsetDecoder :: ByteString -> Maybe (L.ByteString -> TL.Text)

It returns Nothing for charsets the build cannot handle (the CJK charsets
on Windows), so callers fall back to utf-8-lenient decoding without any
CPP of their own.

TypedContent.decoderForCharset now just consults that lookup via a pattern
guard, dropping its encoding imports and #ifdef branches. The Content test
becomes CPP-free too: its fixtures only ever encoded the ASCII payload
"[1,2,3]", which is byte-identical under GB18030/windows-1251/Shift_JIS/
Windows-31J and utf-8, so the CJK-label cases now run on every platform
(exercising the real decoder off-Windows and the fallback on Windows).

The 'encoding' dependency is consequently dropped from the tests stanza
(it builds against the packaged library, not src). The library and
test-routes stanzas keep the `if !os(windows)` gate, since they compile
ContentCharset from source.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Drop the Maybe: extraCharsetDecoder now returns the decoder directly,
owning the utf-8-lenient fallback for unrecognized/unsupported charsets.
The call site in TypedContent.decoderForCharset becomes a plain `otherwise`
branch instead of a pattern guard.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@parsonsmatt
parsonsmatt merged commit 2223392 into master Jun 22, 2026
13 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.

1 participant