diff --git a/oden-js-sys/src/static-functions.rs b/oden-js-sys/src/static-functions.rs index 21a7f957..da619269 100644 --- a/oden-js-sys/src/static-functions.rs +++ b/oden-js-sys/src/static-functions.rs @@ -50,7 +50,7 @@ extern "C" { magic: ::std::os::raw::c_int, ) -> JSValue; fn JS_MakeException_real() -> JSValue; - + fn JS_ValueGetPtr_real(v: JSValue) -> *mut ::std::os::raw::c_void; } pub unsafe fn JS_ValueGetTag(v: JSValue) -> i32 { @@ -217,3 +217,7 @@ pub unsafe fn JS_NewCFunctionMagic( pub unsafe fn JS_MakeException() -> JSValue { JS_MakeException_real() } + +pub unsafe fn JS_ValueGetPtr(v: JSValue) -> *mut ::std::os::raw::c_void { + JS_ValueGetPtr_real(v) +} diff --git a/oden-js-sys/static-functions.c b/oden-js-sys/static-functions.c index 5185ecb1..4aec6a10 100644 --- a/oden-js-sys/static-functions.c +++ b/oden-js-sys/static-functions.c @@ -128,3 +128,7 @@ JSValue JS_NewCFunctionMagic_real(JSContext *ctx, JSCFunctionMagic *func, const JSValue JS_MakeException_real() { return JS_EXCEPTION; } + +void *JS_ValueGetPtr_real(JSValue val) { + return JS_VALUE_GET_PTR(val); +} diff --git a/oden-js/src/context.rs b/oden-js/src/context.rs index 00aa6247..8a748755 100644 --- a/oden-js/src/context.rs +++ b/oden-js/src/context.rs @@ -106,6 +106,14 @@ impl ContextRef { unsafe { sys::JS_EnableBignumExt(self.ctx, if enable { 1 } else { 0 }) } } + pub fn load_module(&self, input: &str, filename: &str) -> Result { + let val = self.eval(input, filename, EvalType::Module, EvalFlags::COMPILE_ONLY)?; + assert!(val.is_module()); + val.eval_function(self)?; + + Ok(val) + } + /// Evaluate the specified JavaScript code. pub fn eval( &self, @@ -482,4 +490,23 @@ mod tests { .unwrap(); assert_eq!(String::from("UNSAFE"), result.to_string(&ctx).unwrap()); } + + #[test] + fn modules_with_exports() { + let ctx = Context::new(Runtime::new()); + let module = ctx + .load_module("const foo = 123; export { foo };", "main.js") + .expect("Could not load!"); + assert_eq!(module.value_type(), ValueType::Module); + + let foo = module + .get_module_export(&ctx, "foo") + .expect("Could not get export"); + assert_eq!(String::from("123"), foo.to_string(&ctx).unwrap()); + + let bar = module + .get_module_export(&ctx, "bar") + .expect("Could not get export"); + assert!(bar.is_undefined()); + } } diff --git a/oden-js/src/value.rs b/oden-js/src/value.rs index 90257483..dbebce06 100644 --- a/oden-js/src/value.rs +++ b/oden-js/src/value.rs @@ -1,6 +1,6 @@ use crate::{AtomRef, ContextRef, Error, Result, Runtime, RustFunction}; use oden_js_sys as sys; -use std::ffi::CStr; +use std::ffi::{CStr, CString}; use std::fmt; use std::ops::{Deref, DerefMut}; @@ -309,6 +309,25 @@ impl ValueRef { Ok(result) } + + pub fn get_module_export(&self, ctx: &ContextRef, export: &str) -> Result { + if self.value_type() != ValueType::Module { + return Err(Error::InvalidType { + expected: ValueType::Bool, + found: self.value_type(), + }); + } + + let c_value = match CString::new(export) { + Ok(cs) => Ok(cs), + Err(_) => Err(Error::UnexpectedNul), + }?; + + unsafe { + let module = sys::JS_ValueGetPtr(self.val) as *mut sys::JSModuleDef; + ctx.check_exception(sys::JS_GetModuleExport(ctx.ctx, module, c_value.into_raw())) + } + } } impl<'ctx> fmt::Debug for ValueRef {