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

Code before:
        // object's top-level origin are not same origin-domain, then return true.
        //
        // TODO: This check doesn't work currently because it seems that comparing two
        // opaque domains doesn't work between GlobalScope::top_level_creation_url and
        // Document::origin().

        // Step 3: If window's relevant agent's event loop's termination nesting level is nonzero,
        // then optionally return true.
        // TODO: This is unsupported currently.

        // Step 4: Optionally, return true. (For example, the user agent might give the
        // user the option to ignore all modal dialogs, and would thus abort at this step
        // whenever the method was invoked.)
        // TODO: The embedder currently cannot block an alert before it is sent to the embedder. This
        // requires changes to the API.

        // Step 5: Return false.
        false
    }

    pub(crate) fn perform_a_microtask_checkpoint(&self, can_gc: CanGc) {
        if let Some(script_thread) = self.weak_script_thread.upgrade() {
            script_thread.perform_a_microtask_checkpoint(can_gc);
        } else {
            info!("Script Thread was already dropped");
        }
    }

    pub(crate) fn web_font_context(&self) -> WebFontDocumentContext {
        let global = self.as_global_scope();
        WebFontDocumentContext {
            policy_container: global.policy_container(),
            request_client: global.request_client(),
            document_url: global.api_base_url(),
            has_trustworthy_ancestor_origin: global.has_trustworthy_ancestor_origin(),
            insecure_requests_policy: global.insecure_requests_policy(),
            csp_handler: Box::new(FontCspHandler {
                global: Trusted::new(global),
                task_source: global
                    .task_manager()
                    .dom_manipulation_task_source()
                    .to_sendable(),
            }),
        }
    }
}

#[derive(Debug)]
struct FontCspHandler {
    global: Trusted<GlobalScope>,
    task_source: SendableTaskSource,

Review comment (refactor):
It should be impossible for the `ScriptThread` to be dropped when this is called, so let's expose a new helper on `Window` right after the `impl Window {` block starts:

```
impl Window {
    pub(crate) fn script_thread(&self) -> Rc<ScriptThread> {
        Weak::upgrade(&self.script_thread)
            .expect("Weak reference should always be upgradable when a ScriptThead is running")
    }
```

Then this would become:

```
    pub(crate) fn perform_a_microtask_checkpoint(&self, can_gc: CanGc) {
        self.script_thread().perform_a_microtask_checkpoint(can_gc)
    }
```

I think it's too much to check the upgradability of the `Weak` handle everywhere we need it.

Code after:
        if self
            .Document()
            .has_active_sandboxing_flag(SandboxingFlagSet::SANDBOXED_MODALS_FLAG)
        {
            return true;
        }

        // Step 2: If window's relevant settings object's origin and window's relevant settings
        // object's top-level origin are not same origin-domain, then return true.
        //
        // TODO: This check doesn't work currently because it seems that comparing two
        // opaque domains doesn't work between GlobalScope::top_level_creation_url and
        // Document::origin().

        // Step 3: If window's relevant agent's event loop's termination nesting level is nonzero,
        // then optionally return true.
        // TODO: This is unsupported currently.

        // Step 4: Optionally, return true. (For example, the user agent might give the
        // user the option to ignore all modal dialogs, and would thus abort at this step
        // whenever the method was invoked.)
        // TODO: The embedder currently cannot block an alert before it is sent to the embedder. This
        // requires changes to the API.

        // Step 5: Return false.
        false
    }

    pub(crate) fn perform_a_microtask_checkpoint(&self, can_gc: CanGc) {
        self.script_thread().perform_a_microtask_checkpoint(can_gc);
    }

    pub(crate) fn web_font_context(&self) -> WebFontDocumentContext {
        let global = self.as_global_scope();
        WebFontDocumentContext {
            policy_container: global.policy_container(),
            request_client: global.request_client(),
            document_url: global.api_base_url(),
            has_trustworthy_ancestor_origin: global.has_trustworthy_ancestor_origin(),
            insecure_requests_policy: global.insecure_requests_policy(),
            csp_handler: Box::new(FontCspHandler {
                global: Trusted::new(global),
                task_source: global
                    .task_manager()
                    .dom_manipulation_task_source()
                    .to_sendable(),
            }),
        }
    }
}