diff --git a/crates/turbopack-ecmascript/src/parse.rs b/crates/turbopack-ecmascript/src/parse.rs index 84dadad3e4c8f..cd86c0e2c7265 100644 --- a/crates/turbopack-ecmascript/src/parse.rs +++ b/crates/turbopack-ecmascript/src/parse.rs @@ -27,6 +27,8 @@ use turbo_tasks_fs::{FileContent, FileSystemPath, FileSystemPathVc}; use turbo_tasks_hash::hash_xxh3_hash64; use turbopack_core::{ asset::{Asset, AssetContent, AssetVc}, + error::PrettyPrintError, + issue::{Issue, IssueSeverity, IssueSeverityVc, IssueVc}, source_map::{GenerateSourceMap, GenerateSourceMapVc, OptionSourceMapVc}, SOURCE_MAP_ROOT_NAME, }; @@ -140,6 +142,20 @@ pub async fn parse( source: AssetVc, ty: Value, transforms: EcmascriptInputTransformsVc, +) -> Result { + match parse_internal(source, ty, transforms).await { + Ok(result) => Ok(result), + Err(error) => Err(error.context(format!( + "failed to parse {}", + source.ident().to_string().await? + ))), + } +} + +async fn parse_internal( + source: AssetVc, + ty: Value, + transforms: EcmascriptInputTransformsVc, ) -> Result { let content = source.content(); let fs_path_vc = source.ident().path(); @@ -147,7 +163,20 @@ pub async fn parse( let ident = &*source.ident().to_string().await?; let file_path_hash = *hash_ident(source.ident().to_string()).await? as u128; let ty = ty.into_value(); - Ok(match &*content.await? { + let content = match content.await { + Ok(content) => content, + Err(error) => { + ReadSourceIssue { + source, + error: PrettyPrintError(&error).to_string(), + } + .cell() + .as_issue() + .emit(); + return Ok(ParseResult::Unparseable.cell()); + } + }; + Ok(match &*content { AssetContent::File(file) => match &*file.await? { FileContent::NotFound => ParseResult::NotFound.cell(), FileContent::Content(file) => match file.content().to_str() { @@ -174,8 +203,16 @@ pub async fn parse( } } } - // FIXME: report error - Err(_) => ParseResult::Unparseable.cell(), + Err(error) => { + ReadSourceIssue { + source, + error: PrettyPrintError(&error).to_string(), + } + .cell() + .as_issue() + .emit(); + ParseResult::Unparseable.cell() + } }, }, AssetContent::Redirect { .. } => ParseResult::Unparseable.cell(), @@ -339,3 +376,43 @@ async fn hash_ident(ident: StringVc) -> Result { let ident = &*ident.await?; Ok(U64Vc::cell(hash_xxh3_hash64(ident))) } + +#[turbo_tasks::value] +struct ReadSourceIssue { + source: AssetVc, + error: String, +} + +#[turbo_tasks::value_impl] +impl Issue for ReadSourceIssue { + #[turbo_tasks::function] + fn context(&self) -> FileSystemPathVc { + self.source.ident().path() + } + + #[turbo_tasks::function] + fn title(&self) -> StringVc { + StringVc::cell("Reading source code for parsing failed".to_string()) + } + + #[turbo_tasks::function] + fn description(&self) -> StringVc { + StringVc::cell( + format!( + "An unexpected error happened while trying to read the source code to parse: {}", + self.error + ) + .into(), + ) + } + + #[turbo_tasks::function] + fn severity(&self) -> IssueSeverityVc { + IssueSeverity::Error.cell() + } + + #[turbo_tasks::function] + fn category(&self) -> StringVc { + StringVc::cell("parse".to_string()) + } +} diff --git a/crates/turbopack-image/src/process/mod.rs b/crates/turbopack-image/src/process/mod.rs index 2481a5529be0d..8747bc8b3556d 100644 --- a/crates/turbopack-image/src/process/mod.rs +++ b/crates/turbopack-image/src/process/mod.rs @@ -33,6 +33,18 @@ pub struct BlurPlaceholder { pub height: u32, } +impl BlurPlaceholder { + pub fn fallback() -> Self { + BlurPlaceholder { + data_url: "data:image/gif;base64,R0lGODlhAQABAIAAAP///\ + wAAACH5BAEAAAAALAAAAAABAAEAAAICRAEAOw==" + .to_string(), + width: 1, + height: 1, + } + } +} + /// Gathered meta information about an image. #[serde_as] #[turbo_tasks::value] @@ -47,6 +59,18 @@ pub struct ImageMetaData { placeholder_for_future_extensions: (), } +impl ImageMetaData { + pub fn fallback_value(mime_type: Option) -> Self { + ImageMetaData { + width: 100, + height: 100, + mime_type, + blur_placeholder: Some(BlurPlaceholder::fallback()), + placeholder_for_future_extensions: (), + } + } +} + /// Options for generating a blur placeholder. #[turbo_tasks::value(shared)] pub struct BlurPlaceholderOptions { @@ -138,7 +162,7 @@ fn compute_blur_data( .cell() .as_issue() .emit(); - None + Some(BlurPlaceholder::fallback()) } } } @@ -253,9 +277,20 @@ pub async fn get_meta_data( let path = ident.path().await?; let extension = path.extension(); if extension == Some("svg") { - let content = std::str::from_utf8(&bytes).context("Input image is not valid utf-8")?; - let (width, height) = - calculate(content).context("Failed to parse svg source code for image dimensions")?; + let content = result_to_issue( + ident, + std::str::from_utf8(&bytes).context("Input image is not valid utf-8"), + ); + let Some(content) = content else { + return Ok(ImageMetaData::fallback_value(Some(mime::IMAGE_SVG)).cell()); + }; + let info = result_to_issue( + ident, + calculate(content).context("Failed to parse svg source code for image dimensions"), + ); + let Some((width, height)) = info else { + return Ok(ImageMetaData::fallback_value(Some(mime::IMAGE_SVG)).cell()); + }; return Ok(ImageMetaData { width, height, @@ -266,7 +301,7 @@ pub async fn get_meta_data( .cell()); } let Some((image, format)) = load_image(ident, &bytes, extension) else { - return Ok(ImageMetaData::default().cell()); + return Ok(ImageMetaData::fallback_value(None).cell()); }; let (width, height) = image.dimensions(); let blur_placeholder = if let Some(blur_placeholder) = blur_placeholder {