@@ -2266,7 +2266,7 @@ type PreprocessorAdditionalData =
22662266
22672267export type SassPreprocessorOptions = {
22682268 additionalData ?: PreprocessorAdditionalData
2269- } & ( { api ?: 'modern' | 'modern-compiler' } & SassModernPreprocessBaseOptions )
2269+ } & SassModernPreprocessBaseOptions
22702270
22712271export type LessPreprocessorOptions = {
22722272 additionalData ?: PreprocessorAdditionalData
@@ -2389,153 +2389,30 @@ function cleanScssBugUrl(url: string) {
23892389
23902390// #region Sass
23912391// .scss/.sass processor
2392- const makeModernScssWorker = (
2392+ const makeScssWorker = (
23932393 environment : PartialEnvironment ,
23942394 resolvers : CSSAtImportResolvers ,
2395- maxWorkers : number | undefined ,
2395+ _maxWorkers : number | undefined ,
23962396) => {
2397- const internalCanonicalize = async (
2398- url : string ,
2399- importer : string ,
2400- ) : Promise < string | null > => {
2401- importer = cleanScssBugUrl ( importer )
2402- const resolved = await resolvers . sass ( environment , url , importer )
2403- return resolved ?? null
2404- }
2405-
2406- const skipRebaseUrls = ( unquotedUrl : string , rawUrl : string ) => {
2407- const isQuoted = rawUrl [ 0 ] === '"' || rawUrl [ 0 ] === "'"
2408- // matches `url($foo)`
2409- if ( ! isQuoted && unquotedUrl [ 0 ] === '$' ) {
2410- return true
2411- }
2412- // matches `url(#{foo})` and `url('#{foo}')`
2413- return unquotedUrl . startsWith ( '#{' )
2414- }
2415-
2416- const internalLoad = async ( file : string , rootFile : string ) => {
2417- const result = await rebaseUrls (
2418- environment ,
2419- file ,
2420- rootFile ,
2421- resolvers . sass ,
2422- skipRebaseUrls ,
2423- )
2424- if ( result . contents ) {
2425- return result . contents
2426- }
2427- return await fsp . readFile ( result . file , 'utf-8' )
2428- }
2397+ let compilerPromise : Promise < Sass . AsyncCompiler > | undefined
24292398
2430- const worker = new WorkerWithFallback (
2431- ( ) =>
2432- async (
2399+ // we use the compiler api provided by sass
2400+ // instead of creating a worker pool on our own
2401+ type WorkerType = InstanceType <
2402+ typeof WorkerWithFallback <
2403+ [
24332404 sassPath : string ,
24342405 data : string ,
24352406 // additionalData can a function that is not cloneable but it won't be used
24362407 options : SassStylePreprocessorInternalOptions & {
2437- api : 'modern'
24382408 additionalData : undefined
24392409 } ,
2440- ) => {
2441- // eslint-disable-next-line no-restricted-globals -- this function runs inside a cjs worker
2442- const sass : typeof Sass = require ( sassPath )
2443- // eslint-disable-next-line no-restricted-globals
2444- const path : typeof import ( 'node:path' ) = require ( 'node:path' )
2445-
2446- const { fileURLToPath, pathToFileURL } : typeof import ( 'node:url' ) =
2447- // eslint-disable-next-line no-restricted-globals
2448- require ( 'node:url' )
2449-
2450- const sassOptions = { ...options } as Sass . StringOptions < 'async' >
2451- sassOptions . url = pathToFileURL ( options . filename )
2452- sassOptions . sourceMap = options . enableSourcemap
2453-
2454- const internalImporter : Sass . Importer < 'async' > = {
2455- async canonicalize ( url , context ) {
2456- const importer = context . containingUrl
2457- ? fileURLToPath ( context . containingUrl )
2458- : options . filename
2459- const resolved = await internalCanonicalize ( url , importer )
2460- if (
2461- resolved &&
2462- // only limit to these extensions because:
2463- // - for the `@import`/`@use`s written in file loaded by `load` function,
2464- // the `canonicalize` function of that `importer` is called first
2465- // - the `load` function of an importer is only called for the importer
2466- // that returned a non-null result from its `canonicalize` function
2467- ( resolved . endsWith ( '.css' ) ||
2468- resolved . endsWith ( '.scss' ) ||
2469- resolved . endsWith ( '.sass' ) )
2470- ) {
2471- return pathToFileURL ( resolved )
2472- }
2473- return null
2474- } ,
2475- async load ( canonicalUrl ) {
2476- const ext = path . extname ( canonicalUrl . pathname )
2477- let syntax : Sass . Syntax = 'scss'
2478- if ( ext === '.sass' ) {
2479- syntax = 'indented'
2480- } else if ( ext === '.css' ) {
2481- syntax = 'css'
2482- }
2483- const contents = await internalLoad (
2484- fileURLToPath ( canonicalUrl ) ,
2485- options . filename ,
2486- )
2487- return { contents, syntax, sourceMapUrl : canonicalUrl }
2488- } ,
2489- }
2490- sassOptions . importers = [
2491- ...( sassOptions . importers ?? [ ] ) ,
2492- internalImporter ,
2493- ]
2494-
2495- const result = await sass . compileStringAsync ( data , sassOptions )
2496- return {
2497- css : result . css ,
2498- map : result . sourceMap ? JSON . stringify ( result . sourceMap ) : undefined ,
2499- stats : {
2500- includedFiles : result . loadedUrls
2501- . filter ( ( url ) => url . protocol === 'file:' )
2502- . map ( ( url ) => fileURLToPath ( url ) ) ,
2503- } ,
2504- } satisfies ScssWorkerResult
2505- } ,
2506- {
2507- parentFunctions : {
2508- internalCanonicalize,
2509- internalLoad,
2510- } ,
2511- shouldUseFake ( _sassPath , _data , options ) {
2512- // functions and importer is a function and is not serializable
2513- // in that case, fallback to running in main thread
2514- return ! ! (
2515- ( options . functions && Object . keys ( options . functions ) . length > 0 ) ||
2516- ( options . importers &&
2517- ( ! Array . isArray ( options . importers ) ||
2518- options . importers . length > 0 ) ) ||
2519- options . logger
2520- )
2521- } ,
2522- max : maxWorkers ,
2523- } ,
2524- )
2525- return worker
2526- }
2527-
2528- // this is mostly a copy&paste of makeModernScssWorker
2529- // however sharing code between two is hard because
2530- // makeModernScssWorker above needs function inlined for worker.
2531- const makeModernCompilerScssWorker = (
2532- environment : PartialEnvironment ,
2533- resolvers : CSSAtImportResolvers ,
2534- _maxWorkers : number | undefined ,
2535- ) => {
2536- let compilerPromise : Promise < Sass . AsyncCompiler > | undefined
2410+ ] ,
2411+ ScssWorkerResult
2412+ >
2413+ >
25372414
2538- const worker : Awaited < ReturnType < typeof makeModernScssWorker > > = {
2415+ const worker : WorkerType = {
25392416 async run ( sassPath , data , options ) {
25402417 // need pathToFileURL for windows since import("D:...") fails
25412418 // https://github.com/nodejs/node/issues/31710
@@ -2632,25 +2509,15 @@ type ScssWorkerResult = {
26322509const scssProcessor = (
26332510 maxWorkers : number | undefined ,
26342511) : StylePreprocessor < SassStylePreprocessorInternalOptions > => {
2635- let worker :
2636- | ReturnType <
2637- typeof makeModernScssWorker | typeof makeModernCompilerScssWorker
2638- >
2639- | undefined
2512+ let worker : ReturnType < typeof makeScssWorker > | undefined
26402513
26412514 return {
26422515 close ( ) {
26432516 worker ?. stop ( )
26442517 } ,
26452518 async process ( environment , source , root , options , resolvers ) {
26462519 const sassPackage = loadSassPackage ( root )
2647- const api =
2648- options . api ??
2649- ( sassPackage . name === 'sass-embedded' ? 'modern-compiler' : 'modern' )
2650- worker ??=
2651- api === 'modern-compiler'
2652- ? makeModernCompilerScssWorker ( environment , resolvers , maxWorkers )
2653- : makeModernScssWorker ( environment , resolvers , maxWorkers )
2520+ worker ??= makeScssWorker ( environment , resolvers , maxWorkers )
26542521
26552522 const { content : data , map : additionalMap } = await getSource (
26562523 source ,
@@ -2667,7 +2534,6 @@ const scssProcessor = (
26672534 const result = await worker . run (
26682535 sassPackage . path ,
26692536 data ,
2670- // @ts -expect-error the correct worker is selected for `options.type`
26712537 optionsWithoutAdditionalData ,
26722538 )
26732539 const deps = result . stats . includedFiles . map ( ( f ) => cleanScssBugUrl ( f ) )
0 commit comments