Repository: awslabs/llrt
File: modules/llrt_fetch/src/request.rs (Rust)

Code before:
    signal: Option<Class<'js, AbortSignal<'js>>>,
    mode: String,
}

impl<'js> Trace<'js> for Request<'js> {
    fn trace<'a>(&self, tracer: rquickjs::class::Tracer<'a, 'js>) {
        if let Some(headers) = &self.headers {
            headers.trace(tracer);
        }
        if let Some(body) = &self.body {
            body.trace(tracer);
        }
    }
}

#[rquickjs::methods(rename_all = "camelCase")]
impl<'js> Request<'js> {
    #[qjs(constructor)]
    pub fn new(ctx: Ctx<'js>, input: Value<'js>, options: Opt<Value<'js>>) -> Result<Self> {
        let mut request = Self {
            url: "".into(),
            method: "GET".into(),
            headers: None,
            body: None,
            signal: None,
            mode: "no-cors".into(),
        };

        if input.is_string() {
            request.url = input.get()?;
        } else if let Ok(url) = URL::from_js(&ctx, input.clone()) {
            request.url = url.to_string();
        } else if input.is_object() {
            assign_request(&mut request, ctx.clone(), unsafe {
                input.as_object().unwrap_unchecked()
            })?;
        }
        if let Some(options) = options.0 {
            if let Some(obj) = options.as_object() {
                assign_request(&mut request, ctx.clone(), obj)?;
            }
        }
        if request.headers.is_none() {
            let headers = Class::instance(ctx, Headers::default())?;
            request.headers = Some(headers);
        }

        Ok(request)
    }

    #[qjs(get)]

Review comment (suggestion):
Default should also be cors as per MDN docs:

> For example, when a Request object is created using the [Request()](https://developer.mozilla.org/en-US/docs/Web/API/Request/Request) constructor, the value of the mode property for that Request is set to cors.

Code after:
impl RequestMode {
    pub fn as_str(&self) -> &str {
        match self {
            Self::Cors => "cors",
            Self::NoCors => "no-cors",
            Self::SameOrigin => "same-origin",
            Self::Navigate => "navigate",
        }
    }
}

impl<'js> Request<'js> {
    async fn take_bytes(&mut self, ctx: &Ctx<'js>) -> Result<Option<ObjectBytes<'js>>> {
        match &self.body {
            Some(provided) => {
                let bytes = if let Some(blob) = get_class::<Blob>(provided)? {
                    ObjectBytes::Vec(blob.borrow().get_bytes())
                } else {
                    ObjectBytes::from(ctx, provided)?
                };
                Ok(Some(bytes))
            },
            None => Ok(None),
        }
    }
}

#[rquickjs::class]
#[derive(rquickjs::JsLifetime)]
pub struct Request<'js> {
    url: String,
    method: String,
    headers: Option<Class<'js, Headers>>,
    body: Option<Value<'js>>,
    signal: Option<Class<'js, AbortSignal<'js>>>,
    mode: RequestMode,
}

impl<'js> Trace<'js> for Request<'js> {
    fn trace<'a>(&self, tracer: rquickjs::class::Tracer<'a, 'js>) {
        if let Some(headers) = &self.headers {
            headers.trace(tracer);
        }
        if let Some(body) = &self.body {
            body.trace(tracer);
        }
    }
}

#[rquickjs::methods(rename_all = "camelCase")]
impl<'js> Request<'js> {