Skip to content

Commit 5bbd5dd

Browse files
authored
Turbopack: improve Lightning CSS error handling (#82561)
Don't return the `Result:Err`, but turn into an issue and return `Unparseable` Also fixes the location translation: Lightning CSS uses 1-based columns, while Turbopack uses 0-based column indices.
1 parent 39fffcc commit 5bbd5dd

File tree

5 files changed

+55
-29
lines changed

5 files changed

+55
-29
lines changed

test/development/acceptance-app/ReactRefreshLogBox.test.ts

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -415,13 +415,13 @@ describe('ReactRefreshLogBox app', () => {
415415
if (isTurbopack) {
416416
await expect(browser).toDisplayRedbox(`
417417
{
418-
"description": "Parsing css source code failed",
418+
"description": "Parsing CSS source code failed",
419419
"environmentLabel": null,
420420
"label": "Build Error",
421-
"source": "./index.module.css (1:9)
422-
Parsing css source code failed
421+
"source": "./index.module.css (1:8)
422+
Parsing CSS source code failed
423423
> 1 | .button
424-
| ^",
424+
| ^",
425425
"stack": [],
426426
}
427427
`)
@@ -447,11 +447,11 @@ describe('ReactRefreshLogBox app', () => {
447447
if (isTurbopack) {
448448
await expect(browser).toDisplayRedbox(`
449449
{
450-
"description": "Parsing css source code failed",
450+
"description": "Transforming CSS failed",
451451
"environmentLabel": null,
452452
"label": "Build Error",
453453
"source": "./index.module.css
454-
Parsing css source code failed
454+
Transforming CSS failed
455455
Selector "button" is not pure. Pure selectors must contain at least one local class or id.
456456
Import traces:
457457
Client Component Browser:

test/development/acceptance/ReactRefreshLogBox.test.ts

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -578,13 +578,13 @@ describe('ReactRefreshLogBox', () => {
578578
if (isTurbopack) {
579579
await expect(browser).toDisplayRedbox(`
580580
{
581-
"description": "Parsing css source code failed",
581+
"description": "Parsing CSS source code failed",
582582
"environmentLabel": null,
583583
"label": "Build Error",
584-
"source": "./index.module.css (1:9)
585-
Parsing css source code failed
584+
"source": "./index.module.css (1:8)
585+
Parsing CSS source code failed
586586
> 1 | .button
587-
| ^",
587+
| ^",
588588
"stack": [],
589589
}
590590
`)
@@ -610,11 +610,11 @@ describe('ReactRefreshLogBox', () => {
610610
if (isTurbopack) {
611611
await expect(browser).toDisplayRedbox(`
612612
{
613-
"description": "Parsing css source code failed",
613+
"description": "Transforming CSS failed",
614614
"environmentLabel": null,
615615
"label": "Build Error",
616616
"source": "./index.module.css
617-
Parsing css source code failed
617+
Transforming CSS failed
618618
Selector "button" is not pure. Pure selectors must contain at least one local class or id.
619619
Import traces:
620620
Browser:

test/development/sass-error/index.test.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@ describe('app dir - css', () => {
2727
// css-loader does not report an error for this case
2828
expect(source).toMatchInlineSnapshot(`
2929
"./app/global.scss.css (45:1)
30-
Parsing css source code failed
30+
Parsing CSS source code failed
3131
43 | }
3232
44 |
3333
> 45 | input.defaultCheckbox::before path {
@@ -36,7 +36,7 @@ describe('app dir - css', () => {
3636
47 | }
3737
48 |
3838
39-
Pseudo-elements like '::before' or '::after' can't be followed by selectors like 'Ident("path")' at [project]/app/global.scss.css:0:884
39+
Pseudo-elements like '::before' or '::after' can't be followed by selectors like 'Ident("path")'
4040
4141
Import trace:
4242
Client Component Browser:

turbopack/crates/turbopack-core/src/issue/mod.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -767,8 +767,8 @@ async fn into_plain_trace(traces: Vec<Vec<ReadRef<AssetIdent>>>) -> Result<Vec<P
767767
Ok(plain_traces)
768768
}
769769

770-
#[turbo_tasks::value(shared, serialization = "none")]
771-
#[derive(Clone, Debug, PartialOrd, Ord, DeterministicHash, Serialize)]
770+
#[turbo_tasks::value(shared)]
771+
#[derive(Clone, Debug, PartialOrd, Ord, DeterministicHash)]
772772
pub enum IssueStage {
773773
Config,
774774
AppStructure,

turbopack/crates/turbopack-css/src/process.rs

Lines changed: 39 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
use std::sync::{Arc, RwLock};
22

3-
use anyhow::{Context, Result, bail};
3+
use anyhow::{Result, bail};
44
use lightningcss::{
55
css_modules::{CssModuleExport, CssModuleExports, Pattern, Segment},
66
stylesheet::{MinifyOptions, ParserOptions, PrinterOptions, StyleSheet, ToCssResult},
@@ -466,8 +466,8 @@ async fn process_content(
466466

467467
// We need to collect here because we need to avoid holding the lock while calling
468468
// `.await` in the loop.
469-
let warngins = warnings.read().unwrap().iter().cloned().collect::<Vec<_>>();
470-
for err in warngins.iter() {
469+
let warnings = warnings.read().unwrap().iter().cloned().collect::<Vec<_>>();
470+
for err in warnings.iter() {
471471
match err.kind {
472472
lightningcss::error::ParserError::UnexpectedToken(_)
473473
| lightningcss::error::ParserError::UnexpectedImportRule
@@ -477,15 +477,16 @@ async fn process_content(
477477
Some(loc) => {
478478
let pos = SourcePos {
479479
line: loc.line as _,
480-
column: loc.column as _,
480+
column: (loc.column - 1) as _,
481481
};
482482
IssueSource::from_line_col(source, pos, pos)
483483
}
484484
None => IssueSource::from_source_only(source),
485485
};
486486

487487
ParsingIssue {
488-
msg: err.to_string().into(),
488+
msg: err.kind.to_string().into(),
489+
stage: IssueStage::Parse,
489490
source,
490491
}
491492
.resolved_cell()
@@ -506,13 +507,30 @@ async fn process_content(
506507
// minify() is actually transform, and it performs operations like CSS modules
507508
// handling.
508509
//
509-
//
510510
// See: https://github.com/parcel-bundler/lightningcss/issues/935#issuecomment-2739325537
511-
ss.minify(MinifyOptions {
511+
if let Err(e) = ss.minify(MinifyOptions {
512512
targets,
513513
..Default::default()
514-
})
515-
.context("failed to transform css")?;
514+
}) {
515+
let source = match &e.loc {
516+
Some(loc) => {
517+
let pos = SourcePos {
518+
line: loc.line as _,
519+
column: (loc.column - 1) as _,
520+
};
521+
IssueSource::from_line_col(source, pos, pos)
522+
}
523+
None => IssueSource::from_source_only(source),
524+
};
525+
ParsingIssue {
526+
msg: e.kind.to_string().into(),
527+
stage: IssueStage::Transform,
528+
source,
529+
}
530+
.resolved_cell()
531+
.emit();
532+
return Ok(ParseCssResult::Unparsable.cell());
533+
}
516534

517535
stylesheet_into_static(&ss, without_warnings(config.clone()))
518536
}
@@ -521,14 +539,15 @@ async fn process_content(
521539
Some(loc) => {
522540
let pos = SourcePos {
523541
line: loc.line as _,
524-
column: loc.column as _,
542+
column: (loc.column - 1) as _,
525543
};
526544
IssueSource::from_line_col(source, pos, pos)
527545
}
528546
None => IssueSource::from_source_only(source),
529547
};
530548
ParsingIssue {
531-
msg: e.to_string().into(),
549+
msg: e.kind.to_string().into(),
550+
stage: IssueStage::Parse,
532551
source,
533552
}
534553
.resolved_cell()
@@ -581,6 +600,7 @@ impl CssError {
581600
least one local class or id."
582601
)
583602
.into(),
603+
stage: IssueStage::Transform,
584604
// TODO: This should include the location of the selector in the file.
585605
source: IssueSource::from_source_only(source),
586606
}
@@ -680,6 +700,7 @@ fn generate_css_source_map(source_map: &parcel_sourcemap::SourceMap) -> Result<R
680700
#[turbo_tasks::value]
681701
struct ParsingIssue {
682702
msg: RcStr,
703+
stage: IssueStage,
683704
source: IssueSource,
684705
}
685706

@@ -692,12 +713,17 @@ impl Issue for ParsingIssue {
692713

693714
#[turbo_tasks::function]
694715
fn stage(&self) -> Vc<IssueStage> {
695-
IssueStage::Parse.cell()
716+
self.stage.clone().cell()
696717
}
697718

698719
#[turbo_tasks::function]
699720
fn title(&self) -> Vc<StyledString> {
700-
StyledString::Text(rcstr!("Parsing css source code failed")).cell()
721+
StyledString::Text(match self.stage {
722+
IssueStage::Parse => rcstr!("Parsing CSS source code failed"),
723+
IssueStage::Transform => rcstr!("Transforming CSS failed"),
724+
_ => rcstr!("CSS processing failed"),
725+
})
726+
.cell()
701727
}
702728

703729
#[turbo_tasks::function]

0 commit comments

Comments
 (0)