diff --git a/Cargo.lock b/Cargo.lock index 07ca3b10fc..4ded396c9f 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1065,6 +1065,7 @@ dependencies = [ "ring", "serde", "slab", + "smallvec", "thiserror", "tokio", "tokio-util", diff --git a/ext/http/Cargo.toml b/ext/http/Cargo.toml index 605615d7ed..9e7d39378c 100644 --- a/ext/http/Cargo.toml +++ b/ext/http/Cargo.toml @@ -46,6 +46,7 @@ pin-project.workspace = true ring.workspace = true serde.workspace = true slab.workspace = true +smallvec.workspace = true thiserror.workspace = true tokio.workspace = true tokio-util = { workspace = true, features = ["io"] } diff --git a/ext/http/http_next.rs b/ext/http/http_next.rs index 9ec9e12c9d..289c387053 100644 --- a/ext/http/http_next.rs +++ b/ext/http/http_next.rs @@ -20,8 +20,10 @@ use cache_control::CacheControl; use deno_core::error::AnyError; use deno_core::futures::TryFutureExt; use deno_core::op; +use deno_core::serde_v8; use deno_core::task::spawn; use deno_core::task::JoinHandle; +use deno_core::v8; use deno_core::AsyncRefCell; use deno_core::AsyncResult; use deno_core::ByteString; @@ -51,11 +53,11 @@ use hyper1::server::conn::http1; use hyper1::server::conn::http2; use hyper1::service::service_fn; use hyper1::service::HttpService; - use hyper1::StatusCode; use once_cell::sync::Lazy; use pin_project::pin_project; use pin_project::pinned_drop; +use smallvec::SmallVec; use std::borrow::Cow; use std::cell::RefCell; use std::future::Future; @@ -255,12 +257,17 @@ pub fn op_http_get_request_header( value.map(|value| value.as_bytes().into()) } -#[op] -pub fn op_http_get_request_headers(slab_id: SlabId) -> Vec { +#[op(v8)] +pub fn op_http_get_request_headers<'scope>( + scope: &mut v8::HandleScope<'scope>, + slab_id: SlabId, +) -> serde_v8::Value<'scope> { let http = slab_get(slab_id); let headers = &http.request_parts().headers; // Two slots for each header key/value pair - let mut vec = Vec::with_capacity(headers.len() * 2); + let mut vec: SmallVec<[v8::Local; 32]> = + SmallVec::with_capacity(headers.len() * 2); + let mut cookies: Option> = None; for (name, value) in headers { if name == COOKIE { @@ -270,9 +277,24 @@ pub fn op_http_get_request_headers(slab_id: SlabId) -> Vec { cookies = Some(vec![value.as_bytes()]); } } else { - let name: &[u8] = name.as_ref(); - vec.push(name.into()); - vec.push(value.as_bytes().into()); + vec.push( + v8::String::new_from_one_byte( + scope, + name.as_ref(), + v8::NewStringType::Normal, + ) + .unwrap() + .into(), + ); + vec.push( + v8::String::new_from_one_byte( + scope, + value.as_bytes(), + v8::NewStringType::Normal, + ) + .unwrap() + .into(), + ); } } @@ -283,11 +305,27 @@ pub fn op_http_get_request_headers(slab_id: SlabId) -> Vec { // TODO(mmastrac): This should probably happen on the JS side on-demand if let Some(cookies) = cookies { let cookie_sep = "; ".as_bytes(); - vec.push(ByteString::from(COOKIE.as_str())); - vec.push(ByteString::from(cookies.join(cookie_sep))); + + vec.push( + v8::String::new_external_onebyte_static(scope, COOKIE.as_ref()) + .unwrap() + .into(), + ); + vec.push( + v8::String::new_from_one_byte( + scope, + cookies.join(cookie_sep).as_ref(), + v8::NewStringType::Normal, + ) + .unwrap() + .into(), + ); } - vec + let array = v8::Array::new_with_elements(scope, vec.as_slice()); + let array_value: v8::Local = array.into(); + + array_value.into() } #[op(fast)]