@@ -207,15 +207,16 @@ async function getSassOptions(
207207 return options ;
208208}
209209
210+ const MODULE_REQUEST_REGEX = / ^ [ ^ ? ] * ~ / ;
211+
210212// Examples:
211213// - ~package
212214// - ~package/
213215// - ~@org
214216// - ~@org/
215217// - ~@org/package
216218// - ~@org/package/
217- const isModuleImport = / ^ ~ ( [ ^ / ] + | [ ^ / ] + \/ | @ [ ^ / ] + [ / ] [ ^ / ] + | @ [ ^ / ] + \/ ? | @ [ ^ / ] + [ / ] [ ^ / ] + \/ ) $ / ;
218- const MODULE_REQUEST_REGEX = / ^ [ ^ ? ] * ~ / ;
219+ const IS_MODULE_IMPORT = / ^ ~ ( [ ^ / ] + | [ ^ / ] + \/ | @ [ ^ / ] + [ / ] [ ^ / ] + | @ [ ^ / ] + \/ ? | @ [ ^ / ] + [ / ] [ ^ / ] + \/ ) $ / ;
219220
220221/**
221222 * When `sass`/`node-sass` tries to resolve an import, it uses a special algorithm.
@@ -244,7 +245,7 @@ function getPossibleRequests(
244245 request = request . replace ( MODULE_REQUEST_REGEX , "" ) ;
245246 }
246247
247- if ( isModuleImport . test ( url ) ) {
248+ if ( IS_MODULE_IMPORT . test ( url ) ) {
248249 request = request [ request . length - 1 ] === "/" ? request : `${ request } /` ;
249250
250251 return [ ...new Set ( [ request , url ] ) ] ;
@@ -310,15 +311,13 @@ const IS_NATIVE_WIN32_PATH = /^[a-z]:[/\\]|^\\\\/i;
310311 * @param {Object } implementation - The imported Sass implementation, both
311312 * `sass` (Dart Sass) and `node-sass` are supported.
312313 * @param {string[] } [includePaths] - The list of include paths passed to Sass.
313- * @param {boolean } [rootContext] - The configured Webpack root context.
314314 *
315315 * @throws If a compatible Sass implementation cannot be found.
316316 */
317317function getWebpackResolver (
318318 resolverFactory ,
319319 implementation ,
320- includePaths = [ ] ,
321- rootContext = false
320+ includePaths = [ ]
322321) {
323322 async function startResolving ( resolutionMap ) {
324323 if ( resolutionMap . length === 0 ) {
@@ -380,6 +379,13 @@ function getWebpackResolver(
380379 ) ;
381380
382381 return ( context , request ) => {
382+ // See https://github.com/webpack/webpack/issues/12340
383+ // Because `node-sass` calls our importer before `1. Filesystem imports relative to the base file.`
384+ // custom importer may not return `{ file: '/path/to/name.ext' }` and therefore our `context` will be relative
385+ if ( ! isDartSass && ! path . isAbsolute ( context ) ) {
386+ return Promise . reject ( ) ;
387+ }
388+
383389 const originalRequest = request ;
384390 const isFileScheme = originalRequest . slice ( 0 , 5 ) . toLowerCase ( ) === "file:" ;
385391
@@ -415,7 +421,7 @@ function getWebpackResolver(
415421 // 4. Filesystem imports relative to an `includePaths` path.
416422 // 5. Filesystem imports relative to a `SASS_PATH` path.
417423 //
418- // Because `sass`/`node- sass` run custom importers before `3`, `4` and `5` points, we need to emulate this behavior to avoid wrong resolution.
424+ // ` sass` run custom importers before `3`, `4` and `5` points, we need to emulate this behavior to avoid wrong resolution.
419425 const sassPossibleRequests = getPossibleRequests ( request ) ;
420426
421427 // `node-sass` calls our importer before `1. Filesystem imports relative to the base file.`, so we need emulate this too
@@ -439,11 +445,7 @@ function getWebpackResolver(
439445 ) ;
440446 }
441447
442- const webpackPossibleRequests = getPossibleRequests (
443- request ,
444- true ,
445- rootContext
446- ) ;
448+ const webpackPossibleRequests = getPossibleRequests ( request , true ) ;
447449
448450 resolutionMap = resolutionMap . concat ( {
449451 resolve : webpackResolve ,
@@ -461,8 +463,7 @@ function getWebpackImporter(loaderContext, implementation, includePaths) {
461463 const resolve = getWebpackResolver (
462464 loaderContext . getResolve ,
463465 implementation ,
464- includePaths ,
465- loaderContext . rootContext
466+ includePaths
466467 ) ;
467468
468469 return ( originalUrl , prev , done ) => {
@@ -472,6 +473,7 @@ function getWebpackImporter(loaderContext, implementation, includePaths) {
472473 // Although we're also using stats.includedFiles, this might come in handy when an error occurs.
473474 // In this case, we don't get stats.includedFiles from node-sass/sass.
474475 loaderContext . addDependency ( path . normalize ( result ) ) ;
476+
475477 // By removing the CSS file extension, we trigger node-sass to include the CSS file instead of just linking it.
476478 done ( { file : result . replace ( matchCss , "" ) } ) ;
477479 } )
0 commit comments