diff --git a/ext/canvas/error.rs b/ext/canvas/error.rs deleted file mode 100644 index e2d1605345..0000000000 --- a/ext/canvas/error.rs +++ /dev/null @@ -1,44 +0,0 @@ -// Copyright 2018-2024 the Deno authors. All rights reserved. MIT license. - -use deno_core::error::AnyError; -use std::borrow::Cow; -use std::fmt; - -#[derive(Debug)] -pub struct DOMExceptionInvalidStateError { - pub msg: String, -} - -impl DOMExceptionInvalidStateError { - pub fn new(msg: &str) -> Self { - DOMExceptionInvalidStateError { - msg: msg.to_string(), - } - } -} - -impl fmt::Display for DOMExceptionInvalidStateError { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - f.pad(&self.msg) - } -} - -impl std::error::Error for DOMExceptionInvalidStateError {} - -pub fn get_error_class_name(e: &AnyError) -> Option<&'static str> { - e.downcast_ref::() - .map(|_| "DOMExceptionInvalidStateError") -} - -/// Returns a string that represents the error message for the image. -pub(crate) fn image_error_message<'a, T: Into>>( - opreation: T, - reason: T, -) -> String { - format!( - "An error has occurred while {}. -reason: {}", - opreation.into(), - reason.into(), - ) -} diff --git a/ext/canvas/image_decoder.rs b/ext/canvas/image_decoder.rs index 7e2464b22b..af56bff37f 100644 --- a/ext/canvas/image_decoder.rs +++ b/ext/canvas/image_decoder.rs @@ -5,7 +5,6 @@ use std::io::BufReader; use std::io::Cursor; use std::io::Seek; -use deno_core::error::AnyError; use image::codecs::bmp::BmpDecoder; use image::codecs::gif::GifDecoder; use image::codecs::ico::IcoDecoder; @@ -15,6 +14,8 @@ use image::codecs::webp::WebPDecoder; use image::DynamicImage; use image::ImageError; +use crate::CanvasError; + // // About the animated image // > Blob .4 @@ -34,15 +35,15 @@ pub(crate) trait ImageDecoderFromReader<'a, R: BufRead + Seek> { /// Create a new image decoder from a reader. fn to_decoder( reader: R, - error_fn: fn(ImageError) -> AnyError, - ) -> Result + error_fn: fn(ImageError) -> CanvasError, + ) -> Result where Self: Sized; /// Convert the image decoder into an intermediate image(DynamicImage). fn to_intermediate_image( self, - error_fn: fn(ImageError) -> AnyError, - ) -> Result; + error_fn: fn(ImageError) -> CanvasError, + ) -> Result; } pub(crate) type ImageDecoderFromReaderType<'a> = BufReader>; @@ -52,8 +53,8 @@ macro_rules! impl_image_decoder_from_reader { impl<'a, R: BufRead + Seek> ImageDecoderFromReader<'a, R> for $decoder { fn to_decoder( reader: R, - error_fn: fn(ImageError) -> AnyError, - ) -> Result + error_fn: fn(ImageError) -> CanvasError, + ) -> Result where Self: Sized, { @@ -64,8 +65,8 @@ macro_rules! impl_image_decoder_from_reader { } fn to_intermediate_image( self, - error_fn: fn(ImageError) -> AnyError, - ) -> Result { + error_fn: fn(ImageError) -> CanvasError, + ) -> Result { match DynamicImage::from_decoder(self) { Ok(image) => Ok(image), Err(err) => Err(error_fn(err)), diff --git a/ext/canvas/image_ops.rs b/ext/canvas/image_ops.rs index 8a8a8ef04e..bc28534550 100644 --- a/ext/canvas/image_ops.rs +++ b/ext/canvas/image_ops.rs @@ -2,8 +2,6 @@ use bytemuck::cast_slice; use bytemuck::cast_slice_mut; -use deno_core::error::type_error; -use deno_core::error::AnyError; use image::ColorType; use image::DynamicImage; use image::GenericImageView; @@ -21,14 +19,7 @@ use lcms2::Transform; use num_traits::NumCast; use num_traits::SaturatingMul; -use crate::error::image_error_message; - -/// Image formats that is 32-bit depth are not supported currently due to the following reasons: -/// - e.g. OpenEXR, it's not covered by the spec. -/// - JPEG XL supported by WebKit, but it cannot be called a standard today. -/// https://github.com/whatwg/mimesniff/issues/143 -const NOT_SUPPORTED_BIT_DEPTH: &str = - "The 32-bit depth image format is not supported."; +use crate::CanvasError; pub(crate) trait PremultiplyAlpha { fn premultiply_alpha(&self) -> Self; @@ -99,7 +90,7 @@ where /// Premultiply the alpha channel of the image. pub(crate) fn premultiply_alpha( image: DynamicImage, -) -> Result { +) -> Result { match image { DynamicImage::ImageLumaA8(image) => { Ok(process_premultiply_alpha(&image).into()) @@ -113,11 +104,11 @@ pub(crate) fn premultiply_alpha( DynamicImage::ImageRgba16(image) => { Ok(process_premultiply_alpha(&image).into()) } - DynamicImage::ImageRgb32F(_) | DynamicImage::ImageRgba32F(_) => { - Err(type_error(image_error_message( - "processing premultiply alpha", - NOT_SUPPORTED_BIT_DEPTH, - ))) + DynamicImage::ImageRgb32F(_) => { + Err(CanvasError::UnsupportedColorType(image.color())) + } + DynamicImage::ImageRgba32F(_) => { + Err(CanvasError::UnsupportedColorType(image.color())) } // If the image does not have an alpha channel, return the image as is. _ => Ok(image), @@ -230,7 +221,7 @@ where /// Invert the premultiplied alpha channel of the image. pub(crate) fn unpremultiply_alpha( image: DynamicImage, -) -> Result { +) -> Result { match image { DynamicImage::ImageLumaA8(image) => Ok(if is_premultiplied_alpha(&image) { process_unpremultiply_alpha(&image).into() @@ -254,11 +245,11 @@ pub(crate) fn unpremultiply_alpha( } else { image.into() }), - DynamicImage::ImageRgb32F(_) | DynamicImage::ImageRgba32F(_) => { - Err(type_error(image_error_message( - "processing un-premultiply alpha", - NOT_SUPPORTED_BIT_DEPTH, - ))) + DynamicImage::ImageRgb32F(_) => { + Err(CanvasError::UnsupportedColorType(image.color())) + } + DynamicImage::ImageRgba32F(_) => { + Err(CanvasError::UnsupportedColorType(image.color())) } // If the image does not have an alpha channel, return the image as is. _ => Ok(image), @@ -366,7 +357,7 @@ where ColorType::Rgb16 => PixelFormat::RGB_16, ColorType::Rgba8 => PixelFormat::RGBA_8, ColorType::Rgba16 => PixelFormat::RGBA_16, - _ => unreachable!("{}", NOT_SUPPORTED_BIT_DEPTH), + _ => unreachable!("{}", CanvasError::UnsupportedColorType(color)), }; let transformer = Transform::new( &input_icc_profile, @@ -393,7 +384,7 @@ where pub(crate) fn to_srgb_from_icc_profile( image: DynamicImage, icc_profile: Option>, -) -> Result { +) -> Result { match icc_profile { // If there is no color profile information, return the image as is. None => Ok(image), @@ -476,10 +467,13 @@ pub(crate) fn to_srgb_from_icc_profile( ) .into(), ), - _ => Err(type_error(image_error_message( - "processing un-premultiply alpha", - NOT_SUPPORTED_BIT_DEPTH, - ))), + DynamicImage::ImageRgb32F(_) => { + Err(CanvasError::UnsupportedColorType(image.color())) + } + DynamicImage::ImageRgba32F(_) => { + Err(CanvasError::UnsupportedColorType(image.color())) + } + _ => Err(CanvasError::UnsupportedColorType(image.color())), } } }, @@ -635,7 +629,7 @@ pub(crate) fn to_srgb_from_icc_profile( // } // /// Convert the color space of the image from sRGB to Display-P3. -// fn srgb_to_display_p3(image: DynamicImage) -> Result { +// fn srgb_to_display_p3(image: DynamicImage) -> Result { // match image { // // The conversion of the lumincance color types to the display-p3 color space is meaningless. // DynamicImage::ImageLuma8(_) diff --git a/ext/canvas/lib.rs b/ext/canvas/lib.rs index 389ed58ff3..5124c60043 100644 --- a/ext/canvas/lib.rs +++ b/ext/canvas/lib.rs @@ -2,7 +2,6 @@ use std::path::PathBuf; -pub mod error; mod image_decoder; mod image_ops; mod op_create_image_bitmap; @@ -11,9 +10,19 @@ use op_create_image_bitmap::op_create_image_bitmap; #[derive(Debug, thiserror::Error)] pub enum CanvasError { - #[error("Color type '{0:?}' not supported")] + /// Image formats that is 32-bit depth are not supported currently due to the following reasons: + /// - e.g. OpenEXR, it's not covered by the spec. + /// - JPEG XL supported by WebKit, but it cannot be called a standard today. + /// https://github.com/whatwg/mimesniff/issues/143 + /// + /// This error will be mapped to TypeError. + #[error("Unsupported color type and bit depth: '{0:?}'")] UnsupportedColorType(ColorType), + /// This error will be mapped to DOMExceptionInvalidStateError. + #[error("Cannot decode image '{0}'")] + InvalidImage(String), #[error(transparent)] + /// This error will be mapped to TypeError. Image(#[from] image::ImageError), } diff --git a/ext/canvas/op_create_image_bitmap.rs b/ext/canvas/op_create_image_bitmap.rs index 2dc7d82497..18f8fce976 100644 --- a/ext/canvas/op_create_image_bitmap.rs +++ b/ext/canvas/op_create_image_bitmap.rs @@ -3,8 +3,6 @@ use std::io::BufReader; use std::io::Cursor; -use deno_core::error::type_error; -use deno_core::error::AnyError; use deno_core::op2; use deno_core::JsBuffer; use deno_core::ToJsBuffer; @@ -22,13 +20,12 @@ use image::ImageDecoder; use image::ImageError; use image::RgbaImage; -use crate::error::image_error_message; -use crate::error::DOMExceptionInvalidStateError; use crate::image_decoder::ImageDecoderFromReader; use crate::image_decoder::ImageDecoderFromReaderType; use crate::image_ops::premultiply_alpha as process_premultiply_alpha; use crate::image_ops::to_srgb_from_icc_profile; use crate::image_ops::unpremultiply_alpha; +use crate::CanvasError; #[derive(Debug, PartialEq)] enum ImageBitmapSource { @@ -83,16 +80,12 @@ fn decode_bitmap_data( height: u32, image_bitmap_source: &ImageBitmapSource, mime_type: MimeType, -) -> Result { +) -> Result { let (image, width, height, orientation, icc_profile) = match image_bitmap_source { ImageBitmapSource::Blob => { - fn image_decoding_error(error: ImageError) -> AnyError { - DOMExceptionInvalidStateError::new(&image_error_message( - "decoding", - &error.to_string(), - )) - .into() + fn image_decoding_error(error: ImageError) -> CanvasError { + CanvasError::InvalidImage(error.to_string()) } let (image, orientation, icc_profile) = match mime_type { // Should we support the "image/apng" MIME type here? @@ -197,10 +190,9 @@ fn decode_bitmap_data( let image = match RgbaImage::from_raw(width, height, buf.into()) { Some(image) => image.into(), None => { - return Err(type_error(image_error_message( - "decoding", - "The Chunk Data is not big enough with the specified width and height.", - ))) + return Err(CanvasError::InvalidImage( + "The Chunk Data is not big enough with the specified width and height.".to_string() + )) } }; @@ -229,7 +221,7 @@ fn apply_color_space_conversion( image: DynamicImage, icc_profile: Option>, color_space_conversion: &ColorSpaceConversion, -) -> Result { +) -> Result { match color_space_conversion { // return the decoded image as is. ColorSpaceConversion::None => Ok(image), @@ -243,7 +235,7 @@ fn apply_premultiply_alpha( image: DynamicImage, image_bitmap_source: &ImageBitmapSource, premultiply_alpha: &PremultiplyAlpha, -) -> Result { +) -> Result { match premultiply_alpha { // 1. PremultiplyAlpha::Default => Ok(image), @@ -386,7 +378,7 @@ pub(super) fn op_create_image_bitmap( resize_quality: u8, image_bitmap_source: u8, mime_type: u8, -) -> Result<(ToJsBuffer, u32, u32), AnyError> { +) -> Result<(ToJsBuffer, u32, u32), CanvasError> { let ParsedArgs { resize_width, resize_height, diff --git a/runtime/errors.rs b/runtime/errors.rs index 869f97968e..47cc40b1bd 100644 --- a/runtime/errors.rs +++ b/runtime/errors.rs @@ -602,7 +602,8 @@ pub fn get_cron_error_class(e: &CronError) -> &'static str { fn get_canvas_error(e: &CanvasError) -> &'static str { match e { CanvasError::UnsupportedColorType(_) => "TypeError", - CanvasError::Image(_) => "Error", + CanvasError::InvalidImage(_) => "DOMExceptionInvalidStateError", + CanvasError::Image(_) => "TypeError", } }