Move Request constructor to impl (#39490)

Doing so allows us to change the type of `init` to take a deref, so that
we can also call it when
implementing `FetchLater` which takes a
`RootedTraceableBox<DeferredRequestInit>`

For more information, see this Zulip thread:

https://servo.zulipchat.com/#narrow/channel/263398-general/topic/How.20to.20upcast.20.60RootedTraceableBox.3CDeferredRequestInit.3E.60/with/540672042

Part of #39448

Signed-off-by: Tim van der Lippe <tvanderlippe@gmail.com>
This commit is contained in:
Tim van der Lippe 2025-09-25 21:30:58 +02:00 committed by GitHub
parent 9804bb9d7b
commit 0ed853102a
No known key found for this signature in database
GPG key ID: B5690EEEBB952194

View file

@ -91,92 +91,13 @@ impl Request {
r r
} }
/// <https://fetch.spec.whatwg.org/#concept-request-clone>
fn clone_from(r: &Request, can_gc: CanGc) -> Fallible<DomRoot<Request>> {
// Step 1. Let newRequest be a copy of request, except for its body.
let req = r.request.borrow();
let url = req.url();
let headers_guard = r.Headers(can_gc).get_guard();
let r_clone = Request::new(&r.global(), None, url, can_gc);
r_clone.request.borrow_mut().pipeline_id = req.pipeline_id;
{
let mut borrowed_r_request = r_clone.request.borrow_mut();
borrowed_r_request.origin = req.origin.clone();
}
*r_clone.request.borrow_mut() = req.clone();
r_clone
.Headers(can_gc)
.copy_from_headers(r.Headers(can_gc))?;
r_clone.Headers(can_gc).set_guard(headers_guard);
// Step 2. If requests body is non-null, set newRequests body to the result of cloning requests body.
// TODO
// Step 3. Return newRequest.
Ok(r_clone)
}
pub(crate) fn get_request(&self) -> NetTraitsRequest {
self.request.borrow().clone()
}
}
fn net_request_from_global(global: &GlobalScope, url: ServoUrl) -> NetTraitsRequest {
RequestBuilder::new(global.webview_id(), url, global.get_referrer())
.origin(global.get_url().origin())
.pipeline_id(Some(global.pipeline_id()))
.https_state(global.get_https_state())
.insecure_requests_policy(global.insecure_requests_policy())
.has_trustworthy_ancestor_origin(global.has_trustworthy_ancestor_or_current_origin())
.build()
}
// https://fetch.spec.whatwg.org/#concept-method-normalize
fn normalize_method(m: &str) -> Result<HttpMethod, InvalidMethod> {
match_ignore_ascii_case! { m,
"delete" => return Ok(HttpMethod::DELETE),
"get" => return Ok(HttpMethod::GET),
"head" => return Ok(HttpMethod::HEAD),
"options" => return Ok(HttpMethod::OPTIONS),
"post" => return Ok(HttpMethod::POST),
"put" => return Ok(HttpMethod::PUT),
_ => (),
}
debug!("Method: {:?}", m);
HttpMethod::from_str(m)
}
// https://fetch.spec.whatwg.org/#concept-method
fn is_method(m: &ByteString) -> bool {
m.as_str().is_some()
}
// https://fetch.spec.whatwg.org/#cors-safelisted-method
fn is_cors_safelisted_method(m: &HttpMethod) -> bool {
m == HttpMethod::GET || m == HttpMethod::HEAD || m == HttpMethod::POST
}
// https://url.spec.whatwg.org/#include-credentials
fn includes_credentials(input: &ServoUrl) -> bool {
!input.username().is_empty() || input.password().is_some()
}
// https://fetch.spec.whatwg.org/#concept-body-disturbed
fn request_is_disturbed(input: &Request) -> bool {
input.is_disturbed()
}
// https://fetch.spec.whatwg.org/#concept-body-locked
fn request_is_locked(input: &Request) -> bool {
input.is_locked()
}
impl RequestMethods<crate::DomTypeHolder> for Request {
// https://fetch.spec.whatwg.org/#dom-request // https://fetch.spec.whatwg.org/#dom-request
fn Constructor( fn constructor(
global: &GlobalScope, global: &GlobalScope,
proto: Option<HandleObject>, proto: Option<HandleObject>,
can_gc: CanGc, can_gc: CanGc,
mut input: RequestInfo, mut input: RequestInfo,
init: RootedTraceableBox<RequestInit>, init: &RequestInit,
) -> Fallible<DomRoot<Request>> { ) -> Fallible<DomRoot<Request>> {
// Step 1. Let request be null. // Step 1. Let request be null.
let temporary_request: NetTraitsRequest; let temporary_request: NetTraitsRequest;
@ -593,6 +514,96 @@ impl RequestMethods<crate::DomTypeHolder> for Request {
Ok(r) Ok(r)
} }
/// <https://fetch.spec.whatwg.org/#concept-request-clone>
fn clone_from(r: &Request, can_gc: CanGc) -> Fallible<DomRoot<Request>> {
// Step 1. Let newRequest be a copy of request, except for its body.
let req = r.request.borrow();
let url = req.url();
let headers_guard = r.Headers(can_gc).get_guard();
let r_clone = Request::new(&r.global(), None, url, can_gc);
r_clone.request.borrow_mut().pipeline_id = req.pipeline_id;
{
let mut borrowed_r_request = r_clone.request.borrow_mut();
borrowed_r_request.origin = req.origin.clone();
}
*r_clone.request.borrow_mut() = req.clone();
r_clone
.Headers(can_gc)
.copy_from_headers(r.Headers(can_gc))?;
r_clone.Headers(can_gc).set_guard(headers_guard);
// Step 2. If requests body is non-null, set newRequests body to the result of cloning requests body.
// TODO
// Step 3. Return newRequest.
Ok(r_clone)
}
pub(crate) fn get_request(&self) -> NetTraitsRequest {
self.request.borrow().clone()
}
}
fn net_request_from_global(global: &GlobalScope, url: ServoUrl) -> NetTraitsRequest {
RequestBuilder::new(global.webview_id(), url, global.get_referrer())
.origin(global.get_url().origin())
.pipeline_id(Some(global.pipeline_id()))
.https_state(global.get_https_state())
.insecure_requests_policy(global.insecure_requests_policy())
.has_trustworthy_ancestor_origin(global.has_trustworthy_ancestor_or_current_origin())
.build()
}
// https://fetch.spec.whatwg.org/#concept-method-normalize
fn normalize_method(m: &str) -> Result<HttpMethod, InvalidMethod> {
match_ignore_ascii_case! { m,
"delete" => return Ok(HttpMethod::DELETE),
"get" => return Ok(HttpMethod::GET),
"head" => return Ok(HttpMethod::HEAD),
"options" => return Ok(HttpMethod::OPTIONS),
"post" => return Ok(HttpMethod::POST),
"put" => return Ok(HttpMethod::PUT),
_ => (),
}
debug!("Method: {:?}", m);
HttpMethod::from_str(m)
}
// https://fetch.spec.whatwg.org/#concept-method
fn is_method(m: &ByteString) -> bool {
m.as_str().is_some()
}
// https://fetch.spec.whatwg.org/#cors-safelisted-method
fn is_cors_safelisted_method(m: &HttpMethod) -> bool {
m == HttpMethod::GET || m == HttpMethod::HEAD || m == HttpMethod::POST
}
// https://url.spec.whatwg.org/#include-credentials
fn includes_credentials(input: &ServoUrl) -> bool {
!input.username().is_empty() || input.password().is_some()
}
// https://fetch.spec.whatwg.org/#concept-body-disturbed
fn request_is_disturbed(input: &Request) -> bool {
input.is_disturbed()
}
// https://fetch.spec.whatwg.org/#concept-body-locked
fn request_is_locked(input: &Request) -> bool {
input.is_locked()
}
impl RequestMethods<crate::DomTypeHolder> for Request {
// https://fetch.spec.whatwg.org/#dom-request
fn Constructor(
global: &GlobalScope,
proto: Option<HandleObject>,
can_gc: CanGc,
input: RequestInfo,
init: RootedTraceableBox<RequestInit>,
) -> Fallible<DomRoot<Request>> {
Self::constructor(global, proto, can_gc, input, &init)
}
// https://fetch.spec.whatwg.org/#dom-request-method // https://fetch.spec.whatwg.org/#dom-request-method
fn Method(&self) -> ByteString { fn Method(&self) -> ByteString {
let r = self.request.borrow(); let r = self.request.borrow();