Skip to content

fix: normalize separators in getPossibleRequests for Windows (#1308)#1309

Merged
alexander-akait merged 3 commits into
mainfrom
claude/fix-issue-1308-BdKjn
May 8, 2026
Merged

fix: normalize separators in getPossibleRequests for Windows (#1308)#1309
alexander-akait merged 3 commits into
mainfrom
claude/fix-issue-1308-BdKjn

Conversation

@alexander-akait

@alexander-akait alexander-akait commented May 7, 2026

Copy link
Copy Markdown
Member

Summary

Fixes #1308 — on Windows the modern API's webpack importer fails to resolve relative SCSS imports inside packages installed under node_modules (e.g. @import './themes/light.scss'; from inside @primer/css/color-modes/index.scss). Same code works on Linux/macOS.

Root cause

When Sass's modern API encounters a relative URL inside a file:-scheme stylesheet, it resolves the URL itself and hands the importer an absolute file: URL with containingUrl === null. sass-loader then converts that URL to a path and feeds it through the webpack resolver.

getPossibleRequests builds variant requests by string-concatenating ${path.dirname(request)}/ + name. On POSIX path.dirname returns forward slashes, matching the hardcoded / joiner — variants are clean. On Windows path.dirname returns backslashes, producing mixed-separator strings like C:\…\themes/_light.scss. enhanced-resolve cannot resolve those (verified locally: even a single mid-path backslash spliced into a POSIX absolute path makes it fail).

This was confirmed not to be a Next.js or enhanced-resolve bug specifically:

  • Next.js's bundled sass-loader@16.0.5 is bit-for-bit identical to upstream — no Next.js-side modification.
  • enhanced-resolve handles all-\ and all-/ absolute Windows paths, but not the mixed form sass-loader feeds it.

Fix

One-line normalization: lowercase path.dirname output to forward slashes so every constructed variant has a single, consistent separator.

- const dirname = path.dirname(request);
+ const dirname = path.dirname(request).replaceAll("\\", "/");

This is platform-agnostic (a no-op on POSIX) and avoids any modern-API-specific special case.

Tests

Added a fixture package whose index.scss does a relative @import './themes/light.scss' (and a sibling for @use), plus a ~pkg/index.scss entry. The test runs across every dart-sass | sass-embedded × legacy | modern | modern-compiler × scss | sass combination — 24 new test cases that exercise the exact bug path.

Test plan

  • npm test — 1676/1676 pass
  • npm run lint — clean
  • CI green on Windows runners (in progress)

Closes #1308

claude added 2 commits May 7, 2026 23:09
In the modern API, Sass resolves relative URLs against the containing
file's URL itself and hands the importer an absolute file: URL with
containingUrl === null. The previous code routed that URL through the
webpack resolver, which on Windows fails because getPossibleRequests
builds variant requests via string concatenation and produces
mixed-separator paths that enhanced-resolve cannot resolve.

Treat the URL as already canonical: verify the file exists with
loaderContext.fs.stat and return it. If the file is missing, return
null so Sass retries with the relative URL form and a populated
containingUrl.

Closes #1308
…t-circuit

Earlier commit added a special-case in getModernWebpackImporter for
absolute file: URLs with containingUrl=null. The actual root cause is
narrower: getPossibleRequests builds variants by concatenating
'${path.dirname(request)}/' with the basename. On Windows path.dirname
returns backslashes, mixing with the hardcoded forward slash and
producing mixed-separator paths like 'C:\\foo/bar.scss' that
enhanced-resolve cannot resolve.

Normalize the dirname output to forward slashes so every variant has a
single, consistent separator. This is a one-liner that fixes the root
cause and works on both POSIX and Windows without any special case.

Refs #1308
@linux-foundation-easycla

linux-foundation-easycla Bot commented May 7, 2026

Copy link
Copy Markdown

CLA Not Signed

@alexander-akait alexander-akait changed the title fix(modern): short-circuit absolute file: URLs in canonicalize fix: normalize separators in getPossibleRequests for Windows (#1308) May 7, 2026
The previous commit added tests for relative @import/@use inside an npm
package but only updated loader.test.js.no-node-sass.snap (the snapshot
file used when node-sass is unavailable). Windows × Node 20 in CI runs
with node-sass installed and consults loader.test.js.snap, which was
missing the new entries — jest's --ci flag forbids creating snapshots,
so the job failed.

Regenerate loader.test.js.snap on Node 20 with node-sass so both
snapshot files are in sync. Adds 78 new snapshot entries (24 dart-sass
+ 24 sass-embedded entries already in the no-node-sass file, plus
30 new ones, of which 4 are node-sass legacy).
@codecov

codecov Bot commented May 8, 2026

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 94.13%. Comparing base (cda2078) to head (ed2d4ce).
⚠️ Report is 2 commits behind head on main.

Additional details and impacted files
@@           Coverage Diff           @@
##             main    #1309   +/-   ##
=======================================
  Coverage   94.13%   94.13%           
=======================================
  Files           3        3           
  Lines         409      409           
  Branches      152      154    +2     
=======================================
  Hits          385      385           
  Misses         22       22           
  Partials        2        2           

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

@alexander-akait alexander-akait merged commit 90e349d into main May 8, 2026
16 of 17 checks passed
@alexander-akait alexander-akait deleted the claude/fix-issue-1308-BdKjn branch May 8, 2026 09:17
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.

[Bug] webpackImporter:true (default) loses path context on Windows when resolving SCSS imports inside node_modules

2 participants