Repository: servo/servo
File: components/script/dom/webgl/webglprogram.rs (Rust)

Code before:
            _ => None,
        }
    }

    pub(crate) fn is_deleted(&self) -> bool {
        self.is_marked_for_deletion() && !self.is_in_use()
    }

    pub(crate) fn detach_shaders(&self) {
        assert!(self.is_deleted());
        if let Some(shader) = self.get_fragment_shader() {
            shader.decrement_attached_counter();
            self.set_fragment_shader(None);
        }
        if let Some(shader) = self.get_vertex_shader() {
            shader.decrement_attached_counter();
            self.set_vertex_shader(None);
        }
    }

    pub(crate) fn mark_for_deletion(&self, operation_fallibility: Operation) {
        if self.marked_for_deletion.get() {
            return;
        }
        self.marked_for_deletion.set(true);
        self.upcast().send_with_fallibility(WebGLCommand::DeleteProgram(self.id()), operation_fallibility);
        if self.is_deleted() {
            self.detach_shaders();
        }
    }

    pub(crate) fn in_use(&self, value: bool) {
        if self.is_in_use() == value {
            return;
        }
        self.set_in_use(value);
        if self.is_deleted() {
            self.detach_shaders();
        }
    }
}

impl Drop for DroppableWebGLProgram {
    fn drop(&mut self) {
        self.in_use(false);
        self.mark_for_deletion(Operation::Fallible);
    }
}

#[dom_struct]
pub(crate) struct WebGLProgram {

Review comment (suggestion):
This is the new code of the mark_for_deletion method, but there is not way to call something of similar to upcast() here @jdm 

Code after:

        self.send_command(WebGLCommand::DetachShader(self.id, shader.id()));

        Ok(shader)
    }

    fn detach_shaders(&mut self) {
        if let Some(ref mut shader) = self.fragment_shader {
            if let Some(root) = shader.root() {
                root.decrement_attached_counter();
                self.send_command(WebGLCommand::DetachShader(self.id, root.id()));
            }
            self.fragment_shader = None;
        }
        if let Some(ref mut shader) = self.vertex_shader {
            if let Some(root) = shader.root() {
                root.decrement_attached_counter();
                self.send_command(WebGLCommand::DetachShader(self.id, root.id()));
            }
            self.vertex_shader = None;
        }
    }

    fn is_deleted(&self) -> bool {
        self.marked_for_deletion && !self.is_in_use
    }

    fn send_command(&self, command: WebGLCommand) {
        self.send_with_fallibility(command, Operation::Infallible);
    }

    fn send_with_fallibility(&self, command: WebGLCommand, fallibility: Operation) {
        if let Some(root) = self.context.root() {
            let result = root.sender().send(command, capture_webgl_backtrace());
            if matches!(fallibility, Operation::Infallible) {
                result.expect("Operation failed");
            }
        }
    }

    fn mark_for_deletion(&mut self, operation_fallibility: Operation) {
        if self.marked_for_deletion {
            return;
        }
        self.marked_for_deletion = true;
        self.send_with_fallibility(WebGLCommand::DeleteProgram(self.id), operation_fallibility);
        if self.is_deleted() {
            self.detach_shaders();
        }
    }