refactor: update deno_core for error refactor (#26867)

Closes #26171

---------

Co-authored-by: David Sherret <dsherret@gmail.com>
This commit is contained in:
Leo Kettmeir 2025-01-08 14:52:32 -08:00 committed by GitHub
parent 814da49dff
commit ea30e188a8
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
214 changed files with 3787 additions and 4210 deletions

View file

@ -28,6 +28,7 @@ brotli.workspace = true
bytes.workspace = true
cache_control.workspace = true
deno_core.workspace = true
deno_error.workspace = true
deno_net.workspace = true
deno_websocket.workspace = true
flate2.workspace = true

View file

@ -146,24 +146,44 @@ macro_rules! clone_external {
}};
}
#[derive(Debug, thiserror::Error)]
#[derive(Debug, thiserror::Error, deno_error::JsError)]
pub enum HttpNextError {
#[class(inherit)]
#[error(transparent)]
Resource(deno_core::error::AnyError),
Resource(#[from] deno_core::error::ResourceError),
#[class(inherit)]
#[error("{0}")]
Io(#[from] io::Error),
#[class(inherit)]
#[error(transparent)]
WebSocketUpgrade(crate::websocket_upgrade::WebSocketUpgradeError),
#[class("Http")]
#[error("{0}")]
Hyper(#[from] hyper::Error),
#[class(inherit)]
#[error(transparent)]
JoinError(#[from] tokio::task::JoinError),
JoinError(
#[from]
#[inherit]
tokio::task::JoinError,
),
#[class(inherit)]
#[error(transparent)]
Canceled(#[from] deno_core::Canceled),
#[error(transparent)]
HttpPropertyExtractor(deno_core::error::AnyError),
Canceled(
#[from]
#[inherit]
deno_core::Canceled,
),
#[class(generic)]
#[error(transparent)]
UpgradeUnavailable(#[from] crate::service::UpgradeUnavailableError),
#[class(inherit)]
#[error("{0}")]
Other(
#[from]
#[inherit]
deno_error::JsErrorBox,
),
}
#[op2(fast)]
@ -747,15 +767,9 @@ pub async fn op_http_set_response_body_resource(
let resource = {
let mut state = state.borrow_mut();
if auto_close {
state
.resource_table
.take_any(stream_rid)
.map_err(HttpNextError::Resource)?
state.resource_table.take_any(stream_rid)?
} else {
state
.resource_table
.get_any(stream_rid)
.map_err(HttpNextError::Resource)?
state.resource_table.get_any(stream_rid)?
}
};
@ -1063,8 +1077,7 @@ where
HTTP: HttpPropertyExtractor,
{
let listener =
HTTP::get_listener_for_rid(&mut state.borrow_mut(), listener_rid)
.map_err(HttpNextError::Resource)?;
HTTP::get_listener_for_rid(&mut state.borrow_mut(), listener_rid)?;
let listen_properties = HTTP::listen_properties_from_listener(&listener)?;
@ -1084,8 +1097,7 @@ where
loop {
let conn = HTTP::accept_connection_from_listener(&listener)
.try_or_cancel(listen_cancel_clone.clone())
.await
.map_err(HttpNextError::HttpPropertyExtractor)?;
.await?;
serve_http_on::<HTTP>(
conn,
&listen_properties_clone,
@ -1120,8 +1132,7 @@ where
HTTP: HttpPropertyExtractor,
{
let connection =
HTTP::get_connection_for_rid(&mut state.borrow_mut(), connection_rid)
.map_err(HttpNextError::Resource)?;
HTTP::get_connection_for_rid(&mut state.borrow_mut(), connection_rid)?;
let listen_properties = HTTP::listen_properties_from_connection(&connection)?;
@ -1190,8 +1201,7 @@ pub async fn op_http_wait(
let join_handle = state
.borrow_mut()
.resource_table
.get::<HttpJoinHandle>(rid)
.map_err(HttpNextError::Resource)?;
.get::<HttpJoinHandle>(rid)?;
let cancel = join_handle.listen_cancel_handle();
let next = async {
@ -1236,7 +1246,7 @@ pub fn op_http_cancel(
state: &mut OpState,
#[smi] rid: ResourceId,
graceful: bool,
) -> Result<(), deno_core::error::AnyError> {
) -> Result<(), deno_core::error::ResourceError> {
let join_handle = state.resource_table.get::<HttpJoinHandle>(rid)?;
if graceful {
@ -1260,8 +1270,7 @@ pub async fn op_http_close(
let join_handle = state
.borrow_mut()
.resource_table
.take::<HttpJoinHandle>(rid)
.map_err(HttpNextError::Resource)?;
.take::<HttpJoinHandle>(rid)?;
if graceful {
http_general_trace!("graceful shutdown");
@ -1390,11 +1399,8 @@ pub async fn op_raw_write_vectored(
#[buffer] buf1: JsBuffer,
#[buffer] buf2: JsBuffer,
) -> Result<usize, HttpNextError> {
let resource: Rc<UpgradeStream> = state
.borrow()
.resource_table
.get::<UpgradeStream>(rid)
.map_err(HttpNextError::Resource)?;
let resource: Rc<UpgradeStream> =
state.borrow().resource_table.get::<UpgradeStream>(rid)?;
let nwritten = resource.write_vectored(&buf1, &buf2).await?;
Ok(nwritten)
}

View file

@ -51,6 +51,7 @@ use deno_core::RcRef;
use deno_core::Resource;
use deno_core::ResourceId;
use deno_core::StringOrBuffer;
use deno_error::JsErrorBox;
use deno_net::raw::NetworkStream;
use deno_websocket::ws_create_server_stream;
use flate2::write::GzEncoder;
@ -165,36 +166,50 @@ deno_core::extension!(
}
);
#[derive(Debug, thiserror::Error)]
#[derive(Debug, thiserror::Error, deno_error::JsError)]
pub enum HttpError {
#[class(inherit)]
#[error(transparent)]
Resource(deno_core::error::AnyError),
Resource(#[from] deno_core::error::ResourceError),
#[class(inherit)]
#[error(transparent)]
Canceled(#[from] deno_core::Canceled),
#[class("Http")]
#[error("{0}")]
HyperV014(#[source] Arc<hyper_v014::Error>),
#[class(generic)]
#[error("{0}")]
InvalidHeaderName(#[from] hyper_v014::header::InvalidHeaderName),
#[class(generic)]
#[error("{0}")]
InvalidHeaderValue(#[from] hyper_v014::header::InvalidHeaderValue),
#[class(generic)]
#[error("{0}")]
Http(#[from] hyper_v014::http::Error),
#[class("Http")]
#[error("response headers already sent")]
ResponseHeadersAlreadySent,
#[class("Http")]
#[error("connection closed while sending response")]
ConnectionClosedWhileSendingResponse,
#[class("Http")]
#[error("already in use")]
AlreadyInUse,
#[class(inherit)]
#[error("{0}")]
Io(#[from] std::io::Error),
#[class("Http")]
#[error("no response headers")]
NoResponseHeaders,
#[class("Http")]
#[error("response already completed")]
ResponseAlreadyCompleted,
#[class("Http")]
#[error("cannot upgrade because request body was used")]
UpgradeBodyUsed,
#[class("Http")]
#[error(transparent)]
Other(deno_core::error::AnyError),
Other(#[from] JsErrorBox),
}
pub enum HttpSocketAddr {
@ -486,7 +501,9 @@ impl Resource for HttpStreamReadResource {
Some(_) => match body.as_mut().next().await.unwrap() {
Ok(chunk) => assert!(chunk.is_empty()),
Err(err) => {
break Err(HttpError::HyperV014(Arc::new(err)).into())
break Err(JsErrorBox::from_err(HttpError::HyperV014(
Arc::new(err),
)))
}
},
None => break Ok(BufView::empty()),
@ -610,11 +627,7 @@ async fn op_http_accept(
state: Rc<RefCell<OpState>>,
#[smi] rid: ResourceId,
) -> Result<Option<NextRequestResponse>, HttpError> {
let conn = state
.borrow()
.resource_table
.get::<HttpConnResource>(rid)
.map_err(HttpError::Resource)?;
let conn = state.borrow().resource_table.get::<HttpConnResource>(rid)?;
match conn.accept().await {
Ok(Some((read_stream, write_stream, method, url))) => {
@ -729,8 +742,7 @@ async fn op_http_write_headers(
let stream = state
.borrow_mut()
.resource_table
.get::<HttpStreamWriteResource>(rid)
.map_err(HttpError::Resource)?;
.get::<HttpStreamWriteResource>(rid)?;
// Track supported encoding
let encoding = stream.accept_encoding;
@ -795,10 +807,7 @@ fn op_http_headers(
state: &mut OpState,
#[smi] rid: u32,
) -> Result<Vec<(ByteString, ByteString)>, HttpError> {
let stream = state
.resource_table
.get::<HttpStreamReadResource>(rid)
.map_err(HttpError::Resource)?;
let stream = state.resource_table.get::<HttpStreamReadResource>(rid)?;
let rd = RcRef::map(&stream, |r| &r.rd)
.try_borrow()
.ok_or(HttpError::AlreadyInUse)?;
@ -954,14 +963,9 @@ async fn op_http_write_resource(
let http_stream = state
.borrow()
.resource_table
.get::<HttpStreamWriteResource>(rid)
.map_err(HttpError::Resource)?;
.get::<HttpStreamWriteResource>(rid)?;
let mut wr = RcRef::map(&http_stream, |r| &r.wr).borrow_mut().await;
let resource = state
.borrow()
.resource_table
.get_any(stream)
.map_err(HttpError::Resource)?;
let resource = state.borrow().resource_table.get_any(stream)?;
loop {
match *wr {
HttpResponseWriter::Headers(_) => {
@ -973,11 +977,7 @@ async fn op_http_write_resource(
_ => {}
};
let view = resource
.clone()
.read(64 * 1024)
.await
.map_err(HttpError::Other)?; // 64KB
let view = resource.clone().read(64 * 1024).await?; // 64KB
if view.is_empty() {
break;
}
@ -1022,8 +1022,7 @@ async fn op_http_write(
let stream = state
.borrow()
.resource_table
.get::<HttpStreamWriteResource>(rid)
.map_err(HttpError::Resource)?;
.get::<HttpStreamWriteResource>(rid)?;
let mut wr = RcRef::map(&stream, |r| &r.wr).borrow_mut().await;
match &mut *wr {
@ -1075,8 +1074,7 @@ async fn op_http_shutdown(
let stream = state
.borrow()
.resource_table
.get::<HttpStreamWriteResource>(rid)
.map_err(HttpError::Resource)?;
.get::<HttpStreamWriteResource>(rid)?;
let mut wr = RcRef::map(&stream, |r| &r.wr).borrow_mut().await;
let wr = take(&mut *wr);
match wr {
@ -1122,8 +1120,7 @@ async fn op_http_upgrade_websocket(
let stream = state
.borrow_mut()
.resource_table
.get::<HttpStreamReadResource>(rid)
.map_err(HttpError::Resource)?;
.get::<HttpStreamReadResource>(rid)?;
let mut rd = RcRef::map(&stream, |r| &r.rd).borrow_mut().await;
let request = match &mut *rd {

View file

@ -15,6 +15,7 @@ use deno_core::AsyncResult;
use deno_core::BufView;
use deno_core::RcRef;
use deno_core::Resource;
use deno_error::JsErrorBox;
use hyper::body::Body;
use hyper::body::Incoming;
use hyper::body::SizeHint;
@ -83,7 +84,10 @@ impl Resource for HttpRequestBody {
}
fn read(self: Rc<Self>, limit: usize) -> AsyncResult<BufView> {
Box::pin(HttpRequestBody::read(self, limit).map_err(Into::into))
Box::pin(
HttpRequestBody::read(self, limit)
.map_err(|e| JsErrorBox::new("Http", e.to_string())),
)
}
fn size_hint(&self) -> (u64, Option<u64>) {

View file

@ -5,9 +5,9 @@ use std::net::SocketAddr;
use std::net::SocketAddrV4;
use std::rc::Rc;
use deno_core::error::AnyError;
use deno_core::OpState;
use deno_core::ResourceId;
use deno_error::JsErrorBox;
use deno_net::raw::take_network_stream_listener_resource;
use deno_net::raw::take_network_stream_resource;
use deno_net::raw::NetworkStream;
@ -50,13 +50,13 @@ pub trait HttpPropertyExtractor {
fn get_listener_for_rid(
state: &mut OpState,
listener_rid: ResourceId,
) -> Result<Self::Listener, AnyError>;
) -> Result<Self::Listener, JsErrorBox>;
/// Given a connection [`ResourceId`], returns the [`HttpPropertyExtractor::Connection`].
fn get_connection_for_rid(
state: &mut OpState,
connection_rid: ResourceId,
) -> Result<Self::Connection, AnyError>;
) -> Result<Self::Connection, JsErrorBox>;
/// Determines the listener properties.
fn listen_properties_from_listener(
@ -71,7 +71,7 @@ pub trait HttpPropertyExtractor {
/// Accept a new [`HttpPropertyExtractor::Connection`] from the given listener [`HttpPropertyExtractor::Listener`].
async fn accept_connection_from_listener(
listener: &Self::Listener,
) -> Result<Self::Connection, AnyError>;
) -> Result<Self::Connection, JsErrorBox>;
/// Determines the connection properties.
fn connection_properties(
@ -103,7 +103,7 @@ impl HttpPropertyExtractor for DefaultHttpPropertyExtractor {
fn get_listener_for_rid(
state: &mut OpState,
listener_rid: ResourceId,
) -> Result<NetworkStreamListener, AnyError> {
) -> Result<NetworkStreamListener, JsErrorBox> {
take_network_stream_listener_resource(
&mut state.resource_table,
listener_rid,
@ -113,17 +113,18 @@ impl HttpPropertyExtractor for DefaultHttpPropertyExtractor {
fn get_connection_for_rid(
state: &mut OpState,
stream_rid: ResourceId,
) -> Result<NetworkStream, AnyError> {
) -> Result<NetworkStream, JsErrorBox> {
take_network_stream_resource(&mut state.resource_table, stream_rid)
.map_err(JsErrorBox::from_err)
}
async fn accept_connection_from_listener(
listener: &NetworkStreamListener,
) -> Result<NetworkStream, AnyError> {
) -> Result<NetworkStream, JsErrorBox> {
listener
.accept()
.await
.map_err(Into::into)
.map_err(JsErrorBox::from_err)
.map(|(stm, _)| stm)
}

View file

@ -9,12 +9,12 @@ use brotli::enc::encode::BrotliEncoderStateStruct;
use brotli::writer::StandardAlloc;
use bytes::Bytes;
use bytes::BytesMut;
use deno_core::error::AnyError;
use deno_core::futures::ready;
use deno_core::futures::FutureExt;
use deno_core::AsyncResult;
use deno_core::BufView;
use deno_core::Resource;
use deno_error::JsErrorBox;
use flate2::write::GzEncoder;
use hyper::body::Frame;
use hyper::body::SizeHint;
@ -32,10 +32,10 @@ pub enum ResponseStreamResult {
/// will only be returned from compression streams that require additional buffering.
NoData,
/// Stream failed.
Error(AnyError),
Error(JsErrorBox),
}
impl From<ResponseStreamResult> for Option<Result<Frame<BufView>, AnyError>> {
impl From<ResponseStreamResult> for Option<Result<Frame<BufView>, JsErrorBox>> {
fn from(value: ResponseStreamResult) -> Self {
match value {
ResponseStreamResult::EndOfStream => None,
@ -411,7 +411,9 @@ impl PollFrame for GZipResponseStream {
};
let len = stm.total_out() - start_out;
let res = match res {
Err(err) => ResponseStreamResult::Error(err.into()),
Err(err) => {
ResponseStreamResult::Error(JsErrorBox::generic(err.to_string()))
}
Ok(flate2::Status::BufError) => {
// This should not happen
unreachable!("old={orig_state:?} new={state:?} buf_len={}", buf.len());

View file

@ -15,6 +15,7 @@ use deno_core::futures::ready;
use deno_core::BufView;
use deno_core::OpState;
use deno_core::ResourceId;
use deno_error::JsErrorBox;
use http::request::Parts;
use hyper::body::Body;
use hyper::body::Frame;
@ -529,7 +530,7 @@ pub struct HttpRecordResponse(ManuallyDrop<Rc<HttpRecord>>);
impl Body for HttpRecordResponse {
type Data = BufView;
type Error = deno_core::error::AnyError;
type Error = JsErrorBox;
fn poll_frame(
self: Pin<&mut Self>,

View file

@ -12,22 +12,30 @@ use memmem::Searcher;
use memmem::TwoWaySearcher;
use once_cell::sync::OnceCell;
#[derive(Debug, thiserror::Error)]
#[derive(Debug, thiserror::Error, deno_error::JsError)]
pub enum WebSocketUpgradeError {
#[class("Http")]
#[error("invalid headers")]
InvalidHeaders,
#[class(generic)]
#[error("{0}")]
HttpParse(#[from] httparse::Error),
#[class(generic)]
#[error("{0}")]
Http(#[from] http::Error),
#[class(generic)]
#[error("{0}")]
Utf8(#[from] std::str::Utf8Error),
#[class(generic)]
#[error("{0}")]
InvalidHeaderName(#[from] http::header::InvalidHeaderName),
#[class(generic)]
#[error("{0}")]
InvalidHeaderValue(#[from] http::header::InvalidHeaderValue),
#[class("Http")]
#[error("invalid HTTP status line")]
InvalidHttpStatusLine,
#[class("Http")]
#[error("attempted to write to completed upgrade buffer")]
UpgradeBufferAlreadyCompleted,
}