oden/oden-js/src/lib.rs
John Doty 5be0ffa08f Starting to mess with promises
Going to want async IO, I think. And it's a fun detail that I guess
I'm in charge of deciding when to run promise completion functions. :D
2023-06-28 15:54:13 -07:00

99 lines
2.9 KiB
Rust

use oden_js_sys as sys;
use std::ffi::{CString, NulError};
use thiserror::Error;
mod atom;
mod callback;
mod class;
mod context;
mod conversion;
pub mod module;
mod promise;
mod runtime;
mod value;
pub use atom::{Atom, AtomRef};
pub use class::{Class, ClassID};
pub use context::{Context, ContextRef, EvalFlags};
pub use conversion::*;
pub use promise::Promise;
pub use runtime::Runtime;
pub use value::{Value, ValueRef, ValueType};
#[derive(Debug, Error)]
pub enum Error {
#[error("too many classes have been registered")]
TooManyClasses,
#[error("the specified value is not an instance of the class {0}")]
WrongClass(String),
#[error("input script contained an embedded NUL byte")]
UnexpectedNul,
#[error("the target context is from a different runtime")]
DifferentRuntime,
#[error("the specified value had the wrong type (expected {expected:?}, found {found:?})")]
InvalidType {
expected: ValueType,
found: ValueType,
},
#[error("argument count mismatch, expected {expected} but received {received}")]
ArgumentCountMismatch { expected: usize, received: usize },
#[error("a conversion error occurred: {0}")]
ConversionError(String),
#[error("an error occurred calling a rust function: {0}")]
RustFunctionError(String),
#[error("an exception was thrown during evaluation: {1}\nStack: {2}")]
Exception(Value, String, String),
#[error("out of memory")]
OutOfMemory,
#[error("an io error occurred: {0}")]
IOError(std::io::Error),
#[error("one or more errors occurred parsing {0}: {1}")]
ParseError(String, String),
}
impl Error {
// Convert the error into an exception-type object which can be
// thrown. This is *different* from try_into_value which just propagates
// the error.
pub fn to_js_error(&self, context: &ContextRef) -> Value {
if let Error::Exception(e, _, _) = self {
e.clone()
} else {
let message = self.to_string();
context.new_error(&message)
}
}
}
impl From<NulError> for Error {
fn from(_: NulError) -> Self {
Error::UnexpectedNul
}
}
impl From<std::io::Error> for Error {
fn from(e: std::io::Error) -> Self {
Error::IOError(e)
}
}
pub type Result<T> = core::result::Result<T, Error>;
pub type ValueResult = core::result::Result<Value, Error>;
pub(crate) fn throw_error(context: &ContextRef, error: Error) -> sys::JSValue {
match error {
Error::Exception(v, _, _) => unsafe {
sys::JS_DupValue(context.ctx, v.val);
sys::JS_Throw(context.ctx, v.val)
},
other => throw_string(context, other.to_string()),
}
}
pub(crate) fn throw_string(context: &ContextRef, message: String) -> sys::JSValue {
let err = context.new_error(&message);
unsafe {
sys::JS_DupValue(context.ctx, err.val);
sys::JS_Throw(context.ctx, err.val)
}
}