mirror of
https://github.com/denoland/deno.git
synced 2024-11-24 15:19:26 -05:00
refactor(ext/webstorage): use concrete error types (#26173)
This commit is contained in:
parent
c5449d71da
commit
cb385d9e4a
5 changed files with 47 additions and 58 deletions
1
Cargo.lock
generated
1
Cargo.lock
generated
|
@ -2235,6 +2235,7 @@ dependencies = [
|
||||||
"deno_core",
|
"deno_core",
|
||||||
"deno_web",
|
"deno_web",
|
||||||
"rusqlite",
|
"rusqlite",
|
||||||
|
"thiserror",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
|
|
|
@ -17,3 +17,4 @@ path = "lib.rs"
|
||||||
deno_core.workspace = true
|
deno_core.workspace = true
|
||||||
deno_web.workspace = true
|
deno_web.workspace = true
|
||||||
rusqlite.workspace = true
|
rusqlite.workspace = true
|
||||||
|
thiserror.workspace = true
|
||||||
|
|
|
@ -2,10 +2,8 @@
|
||||||
|
|
||||||
// NOTE to all: use **cached** prepared statements when interfacing with SQLite.
|
// NOTE to all: use **cached** prepared statements when interfacing with SQLite.
|
||||||
|
|
||||||
use std::fmt;
|
|
||||||
use std::path::PathBuf;
|
use std::path::PathBuf;
|
||||||
|
|
||||||
use deno_core::error::AnyError;
|
|
||||||
use deno_core::op2;
|
use deno_core::op2;
|
||||||
use deno_core::OpState;
|
use deno_core::OpState;
|
||||||
use rusqlite::params;
|
use rusqlite::params;
|
||||||
|
@ -14,6 +12,18 @@ use rusqlite::OptionalExtension;
|
||||||
|
|
||||||
pub use rusqlite;
|
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)]
|
#[derive(Clone)]
|
||||||
struct OriginStorageDir(PathBuf);
|
struct OriginStorageDir(PathBuf);
|
||||||
|
|
||||||
|
@ -51,15 +61,13 @@ struct SessionStorage(Connection);
|
||||||
fn get_webstorage(
|
fn get_webstorage(
|
||||||
state: &mut OpState,
|
state: &mut OpState,
|
||||||
persistent: bool,
|
persistent: bool,
|
||||||
) -> Result<&Connection, AnyError> {
|
) -> Result<&Connection, WebStorageError> {
|
||||||
let conn = if persistent {
|
let conn = if persistent {
|
||||||
if state.try_borrow::<LocalStorage>().is_none() {
|
if state.try_borrow::<LocalStorage>().is_none() {
|
||||||
let path = state.try_borrow::<OriginStorageDir>().ok_or_else(|| {
|
let path = state
|
||||||
DomExceptionNotSupportedError::new(
|
.try_borrow::<OriginStorageDir>()
|
||||||
"LocalStorage is not supported in this context.",
|
.ok_or(WebStorageError::ContextNotSupported)?;
|
||||||
)
|
std::fs::create_dir_all(&path.0).map_err(WebStorageError::Io)?;
|
||||||
})?;
|
|
||||||
std::fs::create_dir_all(&path.0)?;
|
|
||||||
let conn = Connection::open(path.0.join("local_storage"))?;
|
let conn = Connection::open(path.0.join("local_storage"))?;
|
||||||
// Enable write-ahead-logging and tweak some other stuff.
|
// Enable write-ahead-logging and tweak some other stuff.
|
||||||
let initial_pragmas = "
|
let initial_pragmas = "
|
||||||
|
@ -106,7 +114,7 @@ fn get_webstorage(
|
||||||
pub fn op_webstorage_length(
|
pub fn op_webstorage_length(
|
||||||
state: &mut OpState,
|
state: &mut OpState,
|
||||||
persistent: bool,
|
persistent: bool,
|
||||||
) -> Result<u32, AnyError> {
|
) -> Result<u32, WebStorageError> {
|
||||||
let conn = get_webstorage(state, persistent)?;
|
let conn = get_webstorage(state, persistent)?;
|
||||||
|
|
||||||
let mut stmt = conn.prepare_cached("SELECT COUNT(*) FROM data")?;
|
let mut stmt = conn.prepare_cached("SELECT COUNT(*) FROM data")?;
|
||||||
|
@ -121,7 +129,7 @@ pub fn op_webstorage_key(
|
||||||
state: &mut OpState,
|
state: &mut OpState,
|
||||||
#[smi] index: u32,
|
#[smi] index: u32,
|
||||||
persistent: bool,
|
persistent: bool,
|
||||||
) -> Result<Option<String>, AnyError> {
|
) -> Result<Option<String>, WebStorageError> {
|
||||||
let conn = get_webstorage(state, persistent)?;
|
let conn = get_webstorage(state, persistent)?;
|
||||||
|
|
||||||
let mut stmt =
|
let mut stmt =
|
||||||
|
@ -135,14 +143,9 @@ pub fn op_webstorage_key(
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
fn size_check(input: usize) -> Result<(), AnyError> {
|
fn size_check(input: usize) -> Result<(), WebStorageError> {
|
||||||
if input >= MAX_STORAGE_BYTES {
|
if input >= MAX_STORAGE_BYTES {
|
||||||
return Err(
|
return Err(WebStorageError::StorageExceeded);
|
||||||
deno_web::DomExceptionQuotaExceededError::new(
|
|
||||||
"Exceeded maximum storage size",
|
|
||||||
)
|
|
||||||
.into(),
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
|
@ -154,7 +157,7 @@ pub fn op_webstorage_set(
|
||||||
#[string] key: &str,
|
#[string] key: &str,
|
||||||
#[string] value: &str,
|
#[string] value: &str,
|
||||||
persistent: bool,
|
persistent: bool,
|
||||||
) -> Result<(), AnyError> {
|
) -> Result<(), WebStorageError> {
|
||||||
let conn = get_webstorage(state, persistent)?;
|
let conn = get_webstorage(state, persistent)?;
|
||||||
|
|
||||||
size_check(key.len() + value.len())?;
|
size_check(key.len() + value.len())?;
|
||||||
|
@ -178,7 +181,7 @@ pub fn op_webstorage_get(
|
||||||
state: &mut OpState,
|
state: &mut OpState,
|
||||||
#[string] key_name: String,
|
#[string] key_name: String,
|
||||||
persistent: bool,
|
persistent: bool,
|
||||||
) -> Result<Option<String>, AnyError> {
|
) -> Result<Option<String>, WebStorageError> {
|
||||||
let conn = get_webstorage(state, persistent)?;
|
let conn = get_webstorage(state, persistent)?;
|
||||||
|
|
||||||
let mut stmt = conn.prepare_cached("SELECT value FROM data WHERE key = ?")?;
|
let mut stmt = conn.prepare_cached("SELECT value FROM data WHERE key = ?")?;
|
||||||
|
@ -194,7 +197,7 @@ pub fn op_webstorage_remove(
|
||||||
state: &mut OpState,
|
state: &mut OpState,
|
||||||
#[string] key_name: &str,
|
#[string] key_name: &str,
|
||||||
persistent: bool,
|
persistent: bool,
|
||||||
) -> Result<(), AnyError> {
|
) -> Result<(), WebStorageError> {
|
||||||
let conn = get_webstorage(state, persistent)?;
|
let conn = get_webstorage(state, persistent)?;
|
||||||
|
|
||||||
let mut stmt = conn.prepare_cached("DELETE FROM data WHERE key = ?")?;
|
let mut stmt = conn.prepare_cached("DELETE FROM data WHERE key = ?")?;
|
||||||
|
@ -207,7 +210,7 @@ pub fn op_webstorage_remove(
|
||||||
pub fn op_webstorage_clear(
|
pub fn op_webstorage_clear(
|
||||||
state: &mut OpState,
|
state: &mut OpState,
|
||||||
persistent: bool,
|
persistent: bool,
|
||||||
) -> Result<(), AnyError> {
|
) -> Result<(), WebStorageError> {
|
||||||
let conn = get_webstorage(state, persistent)?;
|
let conn = get_webstorage(state, persistent)?;
|
||||||
|
|
||||||
let mut stmt = conn.prepare_cached("DELETE FROM data")?;
|
let mut stmt = conn.prepare_cached("DELETE FROM data")?;
|
||||||
|
@ -221,7 +224,7 @@ pub fn op_webstorage_clear(
|
||||||
pub fn op_webstorage_iterate_keys(
|
pub fn op_webstorage_iterate_keys(
|
||||||
state: &mut OpState,
|
state: &mut OpState,
|
||||||
persistent: bool,
|
persistent: bool,
|
||||||
) -> Result<Vec<String>, AnyError> {
|
) -> Result<Vec<String>, WebStorageError> {
|
||||||
let conn = get_webstorage(state, persistent)?;
|
let conn = get_webstorage(state, persistent)?;
|
||||||
|
|
||||||
let mut stmt = conn.prepare_cached("SELECT key FROM data")?;
|
let mut stmt = conn.prepare_cached("SELECT key FROM data")?;
|
||||||
|
@ -232,31 +235,3 @@ pub fn op_webstorage_iterate_keys(
|
||||||
|
|
||||||
Ok(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")
|
|
||||||
}
|
|
||||||
|
|
|
@ -18,6 +18,7 @@ use deno_core::url;
|
||||||
use deno_core::ModuleResolutionError;
|
use deno_core::ModuleResolutionError;
|
||||||
use deno_cron::CronError;
|
use deno_cron::CronError;
|
||||||
use deno_tls::TlsError;
|
use deno_tls::TlsError;
|
||||||
|
use deno_webstorage::WebStorageError;
|
||||||
use std::env;
|
use std::env;
|
||||||
use std::error::Error;
|
use std::error::Error;
|
||||||
use std::io;
|
use std::io;
|
||||||
|
@ -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 {
|
fn get_tls_error_class(e: &TlsError) -> &'static str {
|
||||||
match e {
|
match e {
|
||||||
TlsError::Rustls(_) => "Error",
|
TlsError::Rustls(_) => "Error",
|
||||||
|
@ -221,7 +231,6 @@ pub fn get_error_class_name(e: &AnyError) -> Option<&'static str> {
|
||||||
deno_core::error::get_custom_error_class(e)
|
deno_core::error::get_custom_error_class(e)
|
||||||
.or_else(|| deno_webgpu::error::get_error_class_name(e))
|
.or_else(|| deno_webgpu::error::get_error_class_name(e))
|
||||||
.or_else(|| deno_web::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(|| deno_websocket::get_network_error_class_name(e))
|
||||||
.or_else(|| e.downcast_ref::<TlsError>().map(get_tls_error_class))
|
.or_else(|| e.downcast_ref::<TlsError>().map(get_tls_error_class))
|
||||||
.or_else(|| e.downcast_ref::<CronError>().map(get_cron_error_class))
|
.or_else(|| e.downcast_ref::<CronError>().map(get_cron_error_class))
|
||||||
|
@ -231,6 +240,10 @@ pub fn get_error_class_name(e: &AnyError) -> Option<&'static str> {
|
||||||
e.downcast_ref::<BroadcastChannelError>()
|
e.downcast_ref::<BroadcastChannelError>()
|
||||||
.map(get_broadcast_channel_error)
|
.map(get_broadcast_channel_error)
|
||||||
})
|
})
|
||||||
|
.or_else(|| {
|
||||||
|
e.downcast_ref::<WebStorageError>()
|
||||||
|
.map(get_webstorage_class_name)
|
||||||
|
})
|
||||||
.or_else(|| {
|
.or_else(|| {
|
||||||
e.downcast_ref::<dlopen2::Error>()
|
e.downcast_ref::<dlopen2::Error>()
|
||||||
.map(get_dlopen_error_class)
|
.map(get_dlopen_error_class)
|
||||||
|
|
|
@ -10,6 +10,7 @@ use crate::web_worker::WorkerControlEvent;
|
||||||
use crate::web_worker::WorkerId;
|
use crate::web_worker::WorkerId;
|
||||||
use crate::web_worker::WorkerMetadata;
|
use crate::web_worker::WorkerMetadata;
|
||||||
use crate::worker::FormatJsErrorFn;
|
use crate::worker::FormatJsErrorFn;
|
||||||
|
use deno_core::error::custom_error;
|
||||||
use deno_core::error::AnyError;
|
use deno_core::error::AnyError;
|
||||||
use deno_core::op2;
|
use deno_core::op2;
|
||||||
use deno_core::serde::Deserialize;
|
use deno_core::serde::Deserialize;
|
||||||
|
@ -136,12 +137,10 @@ fn op_create_worker(
|
||||||
let worker_type = args.worker_type;
|
let worker_type = args.worker_type;
|
||||||
if let WebWorkerType::Classic = worker_type {
|
if let WebWorkerType::Classic = worker_type {
|
||||||
if let TestingFeaturesEnabled(false) = state.borrow() {
|
if let TestingFeaturesEnabled(false) = state.borrow() {
|
||||||
return Err(
|
return Err(custom_error(
|
||||||
deno_webstorage::DomExceptionNotSupportedError::new(
|
"DOMExceptionNotSupportedError",
|
||||||
"Classic workers are not supported.",
|
"Classic workers are not supported.",
|
||||||
)
|
));
|
||||||
.into(),
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue