Skip to content

Commit

Permalink
refactor(ext/webstorage): use concrete error types (#26173)
Browse files Browse the repository at this point in the history
  • Loading branch information
crowlKats authored Oct 14, 2024
1 parent c5449d7 commit cb385d9
Show file tree
Hide file tree
Showing 5 changed files with 47 additions and 58 deletions.
1 change: 1 addition & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions ext/webstorage/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -17,3 +17,4 @@ path = "lib.rs"
deno_core.workspace = true
deno_web.workspace = true
rusqlite.workspace = true
thiserror.workspace = true
77 changes: 26 additions & 51 deletions ext/webstorage/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,8 @@

// NOTE to all: use **cached** prepared statements when interfacing with SQLite.

use std::fmt;
use std::path::PathBuf;

use deno_core::error::AnyError;
use deno_core::op2;
use deno_core::OpState;
use rusqlite::params;
Expand All @@ -14,6 +12,18 @@ use rusqlite::OptionalExtension;

pub use rusqlite;

#[derive(Debug, thiserror::Error)]
pub enum WebStorageError {
#[error("LocalStorage is not supported in this context.")]
ContextNotSupported,
#[error(transparent)]
Sqlite(#[from] rusqlite::Error),
#[error(transparent)]
Io(std::io::Error),
#[error("Exceeded maximum storage size")]
StorageExceeded,
}

#[derive(Clone)]
struct OriginStorageDir(PathBuf);

Expand Down Expand Up @@ -51,15 +61,13 @@ struct SessionStorage(Connection);
fn get_webstorage(
state: &mut OpState,
persistent: bool,
) -> Result<&Connection, AnyError> {
) -> Result<&Connection, WebStorageError> {
let conn = if persistent {
if state.try_borrow::<LocalStorage>().is_none() {
let path = state.try_borrow::<OriginStorageDir>().ok_or_else(|| {
DomExceptionNotSupportedError::new(
"LocalStorage is not supported in this context.",
)
})?;
std::fs::create_dir_all(&path.0)?;
let path = state
.try_borrow::<OriginStorageDir>()
.ok_or(WebStorageError::ContextNotSupported)?;
std::fs::create_dir_all(&path.0).map_err(WebStorageError::Io)?;
let conn = Connection::open(path.0.join("local_storage"))?;
// Enable write-ahead-logging and tweak some other stuff.
let initial_pragmas = "
Expand Down Expand Up @@ -106,7 +114,7 @@ fn get_webstorage(
pub fn op_webstorage_length(
state: &mut OpState,
persistent: bool,
) -> Result<u32, AnyError> {
) -> Result<u32, WebStorageError> {
let conn = get_webstorage(state, persistent)?;

let mut stmt = conn.prepare_cached("SELECT COUNT(*) FROM data")?;
Expand All @@ -121,7 +129,7 @@ pub fn op_webstorage_key(
state: &mut OpState,
#[smi] index: u32,
persistent: bool,
) -> Result<Option<String>, AnyError> {
) -> Result<Option<String>, WebStorageError> {
let conn = get_webstorage(state, persistent)?;

let mut stmt =
Expand All @@ -135,14 +143,9 @@ pub fn op_webstorage_key(
}

#[inline]
fn size_check(input: usize) -> Result<(), AnyError> {
fn size_check(input: usize) -> Result<(), WebStorageError> {
if input >= MAX_STORAGE_BYTES {
return Err(
deno_web::DomExceptionQuotaExceededError::new(
"Exceeded maximum storage size",
)
.into(),
);
return Err(WebStorageError::StorageExceeded);
}

Ok(())
Expand All @@ -154,7 +157,7 @@ pub fn op_webstorage_set(
#[string] key: &str,
#[string] value: &str,
persistent: bool,
) -> Result<(), AnyError> {
) -> Result<(), WebStorageError> {
let conn = get_webstorage(state, persistent)?;

size_check(key.len() + value.len())?;
Expand All @@ -178,7 +181,7 @@ pub fn op_webstorage_get(
state: &mut OpState,
#[string] key_name: String,
persistent: bool,
) -> Result<Option<String>, AnyError> {
) -> Result<Option<String>, WebStorageError> {
let conn = get_webstorage(state, persistent)?;

let mut stmt = conn.prepare_cached("SELECT value FROM data WHERE key = ?")?;
Expand All @@ -194,7 +197,7 @@ pub fn op_webstorage_remove(
state: &mut OpState,
#[string] key_name: &str,
persistent: bool,
) -> Result<(), AnyError> {
) -> Result<(), WebStorageError> {
let conn = get_webstorage(state, persistent)?;

let mut stmt = conn.prepare_cached("DELETE FROM data WHERE key = ?")?;
Expand All @@ -207,7 +210,7 @@ pub fn op_webstorage_remove(
pub fn op_webstorage_clear(
state: &mut OpState,
persistent: bool,
) -> Result<(), AnyError> {
) -> Result<(), WebStorageError> {
let conn = get_webstorage(state, persistent)?;

let mut stmt = conn.prepare_cached("DELETE FROM data")?;
Expand All @@ -221,7 +224,7 @@ pub fn op_webstorage_clear(
pub fn op_webstorage_iterate_keys(
state: &mut OpState,
persistent: bool,
) -> Result<Vec<String>, AnyError> {
) -> Result<Vec<String>, WebStorageError> {
let conn = get_webstorage(state, persistent)?;

let mut stmt = conn.prepare_cached("SELECT key FROM data")?;
Expand All @@ -232,31 +235,3 @@ pub fn op_webstorage_iterate_keys(

Ok(keys)
}

#[derive(Debug)]
pub struct DomExceptionNotSupportedError {
pub msg: String,
}

impl DomExceptionNotSupportedError {
pub fn new(msg: &str) -> Self {
DomExceptionNotSupportedError {
msg: msg.to_string(),
}
}
}

impl fmt::Display for DomExceptionNotSupportedError {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
f.pad(&self.msg)
}
}

impl std::error::Error for DomExceptionNotSupportedError {}

pub fn get_not_supported_error_class_name(
e: &AnyError,
) -> Option<&'static str> {
e.downcast_ref::<DomExceptionNotSupportedError>()
.map(|_| "DOMExceptionNotSupportedError")
}
15 changes: 14 additions & 1 deletion runtime/errors.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ use deno_core::url;
use deno_core::ModuleResolutionError;
use deno_cron::CronError;
use deno_tls::TlsError;
use deno_webstorage::WebStorageError;
use std::env;
use std::error::Error;
use std::io;
Expand Down Expand Up @@ -158,6 +159,15 @@ pub fn get_nix_error_class(error: &nix::Error) -> &'static str {
}
}

fn get_webstorage_class_name(e: &WebStorageError) -> &'static str {
match e {
WebStorageError::ContextNotSupported => "DOMExceptionNotSupportedError",
WebStorageError::Sqlite(_) => todo!(),
WebStorageError::Io(e) => get_io_error_class(e),
WebStorageError::StorageExceeded => "DOMExceptionQuotaExceededError",
}
}

fn get_tls_error_class(e: &TlsError) -> &'static str {
match e {
TlsError::Rustls(_) => "Error",
Expand Down Expand Up @@ -221,7 +231,6 @@ pub fn get_error_class_name(e: &AnyError) -> Option<&'static str> {
deno_core::error::get_custom_error_class(e)
.or_else(|| deno_webgpu::error::get_error_class_name(e))
.or_else(|| deno_web::get_error_class_name(e))
.or_else(|| deno_webstorage::get_not_supported_error_class_name(e))
.or_else(|| deno_websocket::get_network_error_class_name(e))
.or_else(|| e.downcast_ref::<TlsError>().map(get_tls_error_class))
.or_else(|| e.downcast_ref::<CronError>().map(get_cron_error_class))
Expand All @@ -231,6 +240,10 @@ pub fn get_error_class_name(e: &AnyError) -> Option<&'static str> {
e.downcast_ref::<BroadcastChannelError>()
.map(get_broadcast_channel_error)
})
.or_else(|| {
e.downcast_ref::<WebStorageError>()
.map(get_webstorage_class_name)
})
.or_else(|| {
e.downcast_ref::<dlopen2::Error>()
.map(get_dlopen_error_class)
Expand Down
11 changes: 5 additions & 6 deletions runtime/ops/worker_host.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ use crate::web_worker::WorkerControlEvent;
use crate::web_worker::WorkerId;
use crate::web_worker::WorkerMetadata;
use crate::worker::FormatJsErrorFn;
use deno_core::error::custom_error;
use deno_core::error::AnyError;
use deno_core::op2;
use deno_core::serde::Deserialize;
Expand Down Expand Up @@ -136,12 +137,10 @@ fn op_create_worker(
let worker_type = args.worker_type;
if let WebWorkerType::Classic = worker_type {
if let TestingFeaturesEnabled(false) = state.borrow() {
return Err(
deno_webstorage::DomExceptionNotSupportedError::new(
"Classic workers are not supported.",
)
.into(),
);
return Err(custom_error(
"DOMExceptionNotSupportedError",
"Classic workers are not supported.",
));
}
}

Expand Down

0 comments on commit cb385d9

Please sign in to comment.