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

Code before:
    // Step 10. Let controller be null.
    let fetch_context = Arc::new(Mutex::new(FetchContext {
        fetch_promise: Some(TrustedPromise::new(promise.clone())),
        response_object: Trusted::new(&*response),
        resource_timing: ResourceFetchTiming::new(timing_type),
        locally_aborted: false,
    }));

    // Step 11. Add the following abort steps to requestObject’s signal:
    signal.add(&AbortAlgorithm::Fetch(fetch_context.clone()));

    // Step 12. Set controller to the result of calling fetch given request and
    // processResponse given response being these steps:
    global.fetch(
        request_init,
        fetch_context,
        global.task_manager().networking_task_source().to_sendable(),
    );

    // Step 13. Return p.
    promise
}

#[derive(Clone, JSTraceable, MallocSizeOf)]
pub(crate) struct FetchContext {
    #[ignore_malloc_size_of = "unclear ownership semantics"]
    fetch_promise: Option<TrustedPromise>,
    response_object: Trusted<Response>,
    resource_timing: ResourceFetchTiming,
    locally_aborted: bool,
}

impl PreInvoke for FetchContext {}

impl FetchContext {
    /// Step 11 of <https://fetch.spec.whatwg.org/#dom-global-fetch>
    pub(crate) fn abort_fetch(&mut self, reason: HandleValue) {
        // Step 11.1. Set locallyAborted to true.
        self.locally_aborted = true;
        // Step 11.2. Assert: controller is non-null.
        //
        // N/a, that's self

        // Step 11.3. Abort controller with requestObject’s signal’s abort reason.
        // TODO

        // Step 11.4. Abort the fetch() call with p, request, responseObject,
        // and requestObject’s signal’s abort reason.
    }
}


Review comment (bug):
This doesn't work, because the types don't match:

```
error[E0308]: mismatched types
   --> components/script/fetch.rs:239:39
    |
239 |     signal.add(&AbortAlgorithm::Fetch(fetch_context.clone()));
    |                 --------------------- ^^^^^^^^^^^^^^^^^^^^^ expected `FetchContext`, found `Arc<Mutex<FetchContext>>`
    |                 |
    |                 arguments to this enum variant are incorrect
    |
    = note: expected struct `fetch::FetchContext`
               found struct `std::sync::Arc<std::sync::Mutex<fetch::FetchContext>>`
```

Why does it work for `PipeTo` though, since that's also a struct?

Code after:
        RequestPolicyContainer::PolicyContainer(global.policy_container());

    // Step 6. If globalObject is a ServiceWorkerGlobalScope object, then set request’s
    //         service-workers mode to "none".
    if global.is::<ServiceWorkerGlobalScope>() {
        request_init.service_workers_mode = ServiceWorkersMode::None;
    }

    // Step 8. Let relevantRealm be this’s relevant realm.
    //
    // Is `comp` as argument

    // Step 9. Let locallyAborted be false.
    // Step 10. Let controller be null.
    let fetch_context = Arc::new(Mutex::new(FetchContext {
        fetch_promise: Some(TrustedPromise::new(promise.clone())),
        response_object: Trusted::new(&*response),
        request: Trusted::new(&*request_object),
        global: Trusted::new(global),
        resource_timing: ResourceFetchTiming::new(timing_type),
        locally_aborted: false,
        canceller: FetchCanceller::new(request_id, global.core_resource_thread()),
    }));

    // Step 11. Add the following abort steps to requestObject’s signal:
    signal.add(&AbortAlgorithm::Fetch(fetch_context.clone()));

    // Step 12. Set controller to the result of calling fetch given request and
    // processResponse given response being these steps:
    global.fetch(
        request_init,
        fetch_context,
        global.task_manager().networking_task_source().to_sendable(),
    );

    // Step 13. Return p.
    promise
}

#[derive(JSTraceable, MallocSizeOf)]
pub(crate) struct FetchContext {
    #[ignore_malloc_size_of = "unclear ownership semantics"]
    fetch_promise: Option<TrustedPromise>,
    response_object: Trusted<Response>,
    request: Trusted<Request>,
    global: Trusted<GlobalScope>,
    #[no_trace]
    resource_timing: ResourceFetchTiming,
    locally_aborted: bool,
    canceller: FetchCanceller,
}