[oden] Native Modules

This commit is contained in:
John Doty 2023-06-21 06:19:14 -07:00
parent 3b02faf9b4
commit c574fd8cb8
8 changed files with 453 additions and 79 deletions

View file

@ -106,6 +106,7 @@ impl ContextRef {
unsafe { sys::JS_EnableBignumExt(self.ctx, if enable { 1 } else { 0 }) }
}
/// Evaluate the specified JavaScript code as a module.
pub fn load_module(&self, input: &str, filename: &str) -> Result<Value> {
let val = self.eval(input, filename, EvalType::Module, EvalFlags::COMPILE_ONLY)?;
assert!(val.is_module());
@ -122,14 +123,8 @@ impl ContextRef {
eval_type: EvalType,
flags: EvalFlags,
) -> ValueResult {
let c_input = match CString::new(input) {
Ok(cs) => Ok(cs),
Err(_) => Err(Error::UnexpectedNul),
}?;
let c_filename = match CString::new(filename) {
Ok(cs) => Ok(cs),
Err(_) => Err(Error::UnexpectedNul),
}?;
let c_input = CString::new(input)?;
let c_filename = CString::new(filename)?;
let eval_type = match eval_type {
EvalType::Global => sys::JS_EVAL_TYPE_GLOBAL,
@ -150,14 +145,11 @@ impl ContextRef {
/// Construct a new string atom.
pub fn new_atom(&self, value: &str) -> Result<Atom> {
let c_value = match CString::new(value) {
Ok(cs) => Ok(cs),
Err(_) => Err(Error::UnexpectedNul),
}?;
let c_value = CString::new(value)?;
let atom = unsafe { sys::JS_NewAtomLen(self.ctx, c_value.into_raw(), value.len()) };
let atom = unsafe { sys::JS_NewAtomLen(self.ctx, c_value.as_ptr(), value.len()) };
if atom == sys::JS_ATOM_NULL {
return Err(Error::Exception(self.exception()));
return Err(self.exception_error());
}
Ok(Atom::from_raw(atom, self))
@ -241,13 +233,9 @@ impl ContextRef {
/// Construct a new value from a string.
pub fn new_string(&self, value: &str) -> ValueResult {
let c_value = match CString::new(value) {
Ok(cs) => Ok(cs),
Err(_) => Err(Error::UnexpectedNul),
}?;
let c_value = CString::new(value)?;
self.check_exception(unsafe {
sys::JS_NewStringLen(self.ctx, c_value.into_raw(), value.len())
sys::JS_NewStringLen(self.ctx, c_value.as_ptr(), value.len())
})
}
@ -283,7 +271,7 @@ impl ContextRef {
/// error value. Otherwise, just return success with the value, wrapped.
pub(crate) fn check_exception(&self, val: sys::JSValue) -> ValueResult {
if unsafe { sys::JS_ValueGetTag(val) } == sys::JS_TAG_EXCEPTION {
Err(Error::Exception(self.exception()))
Err(self.exception_error())
} else {
Ok(Value::from_raw(val, self))
}
@ -296,6 +284,16 @@ impl ContextRef {
pub(crate) fn exception(&self) -> Value {
Value::from_raw(unsafe { sys::JS_GetException(self.ctx) }, self)
}
/// Fetch the exception value from the context, if any. This is not
/// public because anything that might raise an exception should be
/// returning a Result<> instead, to separate the exception flow from the
/// value flow.
pub(crate) fn exception_error(&self) -> Error {
let exc = self.exception();
let desc = exc.to_string(&self).unwrap_or_else(|_| String::new());
Error::Exception(exc, desc)
}
}
#[derive(Debug)]