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

Code before:
                    .source_signals
                    .borrow_mut()
                    .insert(WeakRef::new(signal));
                // Step 4.1.2. Append resultSignal to signal’s dependent signals.
                signal
                    .dependent_signals
                    .borrow_mut()
                    .insert(WeakRef::new(&*result_signal));
            } else {
                // Step 4.2. Otherwise, for each sourceSignal of signal’s source signals:
                for source_signal_weak in signal.source_signals.borrow().iter() {
                    if let Some(source_signal) = source_signal_weak.root() {
                        // Step 4.2.1. Assert: sourceSignal is not aborted and not dependent.
                        assert!(!source_signal.aborted() && !source_signal.dependent.get());
                        // Step 4.2.2. Append sourceSignal to resultSignal’s source signals.
                        result_signal
                            .source_signals
                            .borrow_mut()
                            .insert(WeakRef::new(&*source_signal));
                        // Step 4.2.3. Append resultSignal to sourceSignal’s dependent signals.
                        source_signal
                            .dependent_signals
                            .borrow_mut()
                            .insert(WeakRef::new(&*result_signal));
                    }
                    // else: underlying source signal was GC'd; we can just ignore this entry.
                }
            }
        }
        // Step 5. Return resultSignal.
        global.register_dependent_abort_signal(&result_signal);
        result_signal
    }

    /// Remove weak references whose target has been collected.
    fn prune_dead_weak_refs(&self) {
        self.source_signals.borrow_mut().retain(|w| w.is_alive());
        self.dependent_signals.borrow_mut().retain(|w| w.is_alive());
    }

    /// Whether this signal still has abort algorithms registered.
    fn has_abort_algorithms(&self) -> bool {
        !self.abort_algorithms.borrow().is_empty()
    }

    /// Whether this signal has any listeners for its "abort" event.
    fn has_abort_listeners(&self) -> bool {
        self.upcast::<EventTarget>()
            .has_listeners_for(&atom!("abort"))
    }


Review comment (bug):
I think we should panic if the source signal was gc'd, since the assertion in step 4.2.1 would fail, no?

(Also this could be a `let ... else` expression which would be slightly more concise)

Code after:
                    .source_signals
                    .borrow_mut()
                    .insert(WeakRef::new(signal));
                // Step 4.1.2. Append resultSignal to signal’s dependent signals.
                signal
                    .dependent_signals
                    .borrow_mut()
                    .insert(WeakRef::new(&*result_signal));
            } else {
                // Step 4.2. Otherwise, for each sourceSignal of signal’s source signals:
                for source_signal_weak in signal.source_signals.borrow().iter() {
                    if let Some(source_signal) = source_signal_weak.root() {
                        // Step 4.2.1. Assert: sourceSignal is not aborted and not dependent.
                        assert!(!source_signal.aborted() && !source_signal.dependent.get());
                        // Step 4.2.2. Append sourceSignal to resultSignal’s source signals.
                        result_signal
                            .source_signals
                            .borrow_mut()
                            .insert(WeakRef::new(&*source_signal));
                        // Step 4.2.3. Append resultSignal to sourceSignal’s dependent signals.
                        source_signal
                            .dependent_signals
                            .borrow_mut()
                            .insert(WeakRef::new(&*result_signal));
                    }
                }
            }
        }
        // Step 5. Return resultSignal.
        global.register_dependent_abort_signal(&result_signal);
        result_signal
    }

    /// Remove weak references whose target has been collected.
    fn prune_dead_weak_refs(&self) {
        self.source_signals.borrow_mut().retain(|w| w.is_alive());
        self.dependent_signals.borrow_mut().retain(|w| w.is_alive());
    }

    /// Whether this signal still has abort algorithms registered.
    fn has_abort_algorithms(&self) -> bool {
        !self.abort_algorithms.borrow().is_empty()
    }

    /// Whether this signal has any listeners for its "abort" event.
    fn has_abort_listeners(&self) -> bool {
        self.upcast::<EventTarget>()
            .has_listeners_for(&atom!("abort"))
    }

    /// <https://dom.spec.whatwg.org/#abort-signal-garbage-collection>