Repository: servo/servo
File: components/net/image_cache.rs (Rust)

Code before:
                    );
                }
            }
        }
    }

    fn remove_rasterized_vector_image(
        &mut self,
        image_id: &PendingImageId,
        device_size: &DeviceIntSize,
    ) {
        if let Some(entry) = self
            .rasterized_vector_images
            .remove(&(*image_id, *device_size))
        {
            // If there is no corresponding rasterized_vector_image result,
            // then the vector image is either being rasterized or is in
            // self.store.key_cache.pending_image_keys. Either way, we need to notify the
            // KeyCache that it was evicted.
            if entry.result.is_none() {
                self.evict_image_from_keycache(image_id, device_size);
            } else {
                if let Some(image_id) = entry.result.as_ref().unwrap().id {
                    self.paint_api.update_images(
                        self.webview_id.into(),
                        vec![ImageUpdate::DeleteImage(image_id)].into(),
                    );
                }
            }
        }
    }

    /// Return a completed image if it exists, or None if there is no complete load
    /// or the complete load is not fully decoded or is unavailable.
    fn get_completed_image_if_available(
        &self,
        url: ServoUrl,
        origin: ImmutableOrigin,
        cors_setting: Option<CorsSettings>,
    ) -> Option<Result<(Image, ServoUrl), ()>> {
        self.completed_loads
            .get(&(url, origin, cors_setting))
            .map(|completed_load| match &completed_load.image_response {
                ImageResponse::Loaded(image, url) => Ok((image.clone(), url.clone())),
                ImageResponse::FailedToLoadOrDecode | ImageResponse::MetadataLoaded(_) => Err(()),
            })
    }

    /// Handle a message from one of the decoder worker threads or from a sync
    /// decoding operation.
    fn handle_decoder(&mut self, msg: DecoderMsg) {

Review comment (performance):
I'm thinking it would be nice to do this once per iteration of the event for all images that have been evicted.

For example one could store the ids on the cache, and then update the paint api for all by calling into the cache as part of the existing [`perform_a_dom_garbage_collection_checkpoint`](https://github.com/servo/servo/blob/0112ffa812cab93899e4eb2df6aae6ecac2d97e4/components/script/script_thread.rs#L1460).

You could file an issue for this so it can be investigated and done in a follow-up.

Code after:
                }
            }
        }
    }

    fn remove_rasterized_vector_image(
        &mut self,
        image_id: &PendingImageId,
        device_size: &DeviceIntSize,
    ) {
        if let Some(entry) = self
            .rasterized_vector_images
            .remove(&(*image_id, *device_size))
        {
            // If there is no corresponding rasterized_vector_image result,
            // then the vector image is either being rasterized or is in
            // self.store.key_cache.pending_image_keys. Either way, we need to notify the
            // KeyCache that it was evicted.
            if entry.result.is_none() {
                self.evict_image_from_keycache(image_id, device_size);
            } else if let Some(image_id) = entry.result.as_ref().unwrap().id {
                self.paint_api.update_images(
                    self.webview_id.into(),
                    vec![ImageUpdate::DeleteImage(image_id)].into(),
                );
            }
        }
    }

    /// Return a completed image if it exists, or None if there is no complete load
    /// or the complete load is not fully decoded or is unavailable.
    fn get_completed_image_if_available(
        &self,
        url: ServoUrl,
        origin: ImmutableOrigin,
        cors_setting: Option<CorsSettings>,
    ) -> Option<Result<(Image, ServoUrl), ()>> {
        self.completed_loads
            .get(&(url, origin, cors_setting))
            .map(|completed_load| match &completed_load.image_response {
                ImageResponse::Loaded(image, url) => Ok((image.clone(), url.clone())),
                ImageResponse::FailedToLoadOrDecode | ImageResponse::MetadataLoaded(_) => Err(()),
            })
    }

    /// Handle a message from one of the decoder worker threads or from a sync
    /// decoding operation.
    fn handle_decoder(&mut self, msg: DecoderMsg) {
        let image = match msg.image {
            None => LoadResult::FailedToLoadOrDecode,
            Some(DecodedImage::Raster(raster_image)) => {