diff --git a/oden-js-sys/src/lib.rs b/oden-js-sys/src/lib.rs index 28fd1a09..49d5c5a7 100644 --- a/oden-js-sys/src/lib.rs +++ b/oden-js-sys/src/lib.rs @@ -7,9 +7,34 @@ include!("static-functions.rs"); use std::fmt; +fn tag_name(tag: i64) -> &'static str { + match tag.try_into() { + Ok(tag) => match tag { + JS_TAG_BIG_DECIMAL => "JS_TAG_BIG_DECIMAL", + JS_TAG_BIG_INT => "JS_TAG_BIG_INT", + JS_TAG_BIG_FLOAT => "JS_TAG_BIG_FLOAT", + JS_TAG_SYMBOL => "JS_TAG_SYMBOL", + JS_TAG_MODULE => "JS_TAG_MODULE", + JS_TAG_FUNCTION_BYTECODE => "JS_TAG_FUNCTION_BYTECODE", + JS_TAG_STRING => "JS_TAG_STRING", + JS_TAG_OBJECT => "JS_TAG_OBJECT", + JS_TAG_INT => "JS_TAG_INT", + JS_TAG_BOOL => "JS_TAG_BOOL", + JS_TAG_NULL => "JS_TAG_NULL", + JS_TAG_UNDEFINED => "JS_TAG_UNDEFINED", + JS_TAG_UNINITIALIZED => "JS_TAG_UNINITIALIZED", + JS_TAG_CATCH_OFFSET => "JS_TAG_CATCH_OFFSET", + JS_TAG_EXCEPTION => "JS_TAG_EXCEPTION", + JS_TAG_FLOAT64 => "JS_TAG_FLOAT64", + _ => "???", + }, + Err(_) => "???", + } +} + impl fmt::Debug for JSValue { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - write!(f, "JS[{}", self.tag)?; + write!(f, "JS[{} ({})", tag_name(self.tag), self.tag)?; if self.tag < 0 { write!(f, " {:?}]", unsafe { self.u.ptr }) } else { diff --git a/oden-js-sys/src/static-functions.rs b/oden-js-sys/src/static-functions.rs index fb40a012..25222d25 100644 --- a/oden-js-sys/src/static-functions.rs +++ b/oden-js-sys/src/static-functions.rs @@ -8,25 +8,25 @@ extern "C" { fn JS_DupValueRT_real(rt: *mut JSRuntime, v: JSValue); fn JS_FreeValue_real(ctx: *mut JSContext, v: JSValue); fn JS_FreeValueRT_real(rt: *mut JSRuntime, v: JSValue); - fn JS_NewBool_real(ctx: *mut JSContext, v: bool) -> JSValue; + fn JS_NewBool_real(ctx: *mut JSContext, v: ::std::os::raw::c_int) -> JSValue; fn JS_NewInt32_real(ctx: *mut JSContext, v: i32) -> JSValue; fn JS_NewUint32_real(ctx: *mut JSContext, v: u32) -> JSValue; fn JS_NewFloat64_real(ctx: *mut JSContext, v: f64) -> JSValue; - fn JS_VALUE_IS_NAN_real(v: JSValue) -> bool; + fn JS_VALUE_IS_NAN_real(v: JSValue) -> ::std::os::raw::c_int; fn JS_VALUE_GET_FLOAT64_real(v: JSValue) -> f64; fn JS_VALUE_GET_NORM_TAG_real(v: JSValue) -> ::std::os::raw::c_int; - fn JS_IsNumber_real(v: JSValue) -> bool; - fn JS_IsBigInt_real(ctx: *mut JSContext, v: JSValue) -> bool; - fn JS_IsBigFloat_real(v: JSValue) -> bool; - fn JS_IsBigDecimal_real(v: JSValue) -> bool; - fn JS_IsBool_real(v: JSValue) -> bool; - fn JS_IsNull_real(v: JSValue) -> bool; - fn JS_IsUndefined_real(v: JSValue) -> bool; - fn JS_IsException_real(v: JSValue) -> bool; - fn JS_IsUninitialized_real(v: JSValue) -> bool; - fn JS_IsString_real(v: JSValue) -> bool; - fn JS_IsSymbol_real(v: JSValue) -> bool; - fn JS_IsObject_real(v: JSValue) -> bool; + fn JS_IsNumber_real(v: JSValue) -> ::std::os::raw::c_int; + fn JS_IsBigInt_real(ctx: *mut JSContext, v: JSValue) -> ::std::os::raw::c_int; + fn JS_IsBigFloat_real(v: JSValue) -> ::std::os::raw::c_int; + fn JS_IsBigDecimal_real(v: JSValue) -> ::std::os::raw::c_int; + fn JS_IsBool_real(v: JSValue) -> ::std::os::raw::c_int; + fn JS_IsNull_real(v: JSValue) -> ::std::os::raw::c_int; + fn JS_IsUndefined_real(v: JSValue) -> ::std::os::raw::c_int; + fn JS_IsException_real(v: JSValue) -> ::std::os::raw::c_int; + fn JS_IsUninitialized_real(v: JSValue) -> ::std::os::raw::c_int; + fn JS_IsString_real(v: JSValue) -> ::std::os::raw::c_int; + fn JS_IsSymbol_real(v: JSValue) -> ::std::os::raw::c_int; + fn JS_IsObject_real(v: JSValue) -> ::std::os::raw::c_int; fn JS_ToUint32_real(ctx: *mut JSContext, pres: *mut u32, val: JSValue) -> i32; fn JS_GetProperty_real(ctx: *mut JSContext, this_obj: JSValue, prop: JSAtom) -> JSValue; fn JS_SetProperty_real( @@ -82,7 +82,7 @@ pub unsafe fn JS_FreeValueRT(rt: *mut JSRuntime, v: JSValue) { } /// create a new boolean value -pub unsafe fn JS_NewBool(ctx: *mut JSContext, v: bool) -> JSValue { +pub unsafe fn JS_NewBool(ctx: *mut JSContext, v: ::std::os::raw::c_int) -> JSValue { JS_NewBool_real(ctx, v) } @@ -102,7 +102,7 @@ pub unsafe fn JS_NewFloat64(ctx: *mut JSContext, v: f64) -> JSValue { } /// check if a JSValue is a NaN value -pub unsafe fn JS_VALUE_IS_NAN(v: JSValue) -> bool { +pub unsafe fn JS_VALUE_IS_NAN(v: JSValue) -> ::std::os::raw::c_int { JS_VALUE_IS_NAN_real(v) } @@ -117,62 +117,62 @@ pub unsafe fn JS_VALUE_GET_NORM_TAG(v: JSValue) -> ::std::os::raw::c_int { } /// check if a JSValue is a Number -pub unsafe fn JS_IsNumber(v: JSValue) -> bool { +pub unsafe fn JS_IsNumber(v: JSValue) -> ::std::os::raw::c_int { JS_IsNumber_real(v) } /// check if a JSValue is a BigInt -pub unsafe fn JS_IsBigInt(ctx: *mut JSContext, v: JSValue) -> bool { +pub unsafe fn JS_IsBigInt(ctx: *mut JSContext, v: JSValue) -> ::std::os::raw::c_int { JS_IsBigInt_real(ctx, v) } /// check if a JSValue is a BigFloat -pub unsafe fn JS_IsBigFloat(v: JSValue) -> bool { +pub unsafe fn JS_IsBigFloat(v: JSValue) -> ::std::os::raw::c_int { JS_IsBigFloat_real(v) } /// check if a JSValue is a BigDecimal -pub unsafe fn JS_IsBigDecimal(v: JSValue) -> bool { +pub unsafe fn JS_IsBigDecimal(v: JSValue) -> ::std::os::raw::c_int { JS_IsBigDecimal_real(v) } /// check if a JSValue is a Boolean -pub unsafe fn JS_IsBool(v: JSValue) -> bool { +pub unsafe fn JS_IsBool(v: JSValue) -> ::std::os::raw::c_int { JS_IsBool_real(v) } /// check if a JSValue is null -pub unsafe fn JS_IsNull(v: JSValue) -> bool { +pub unsafe fn JS_IsNull(v: JSValue) -> ::std::os::raw::c_int { JS_IsNull_real(v) } /// check if a JSValue is Undefined -pub unsafe fn JS_IsUndefined(v: JSValue) -> bool { +pub unsafe fn JS_IsUndefined(v: JSValue) -> ::std::os::raw::c_int { JS_IsUndefined_real(v) } /// check if a JSValue is an Exception -pub unsafe fn JS_IsException(v: JSValue) -> bool { +pub unsafe fn JS_IsException(v: JSValue) -> ::std::os::raw::c_int { JS_IsException_real(v) } /// check if a JSValue is initialized -pub unsafe fn JS_IsUninitialized(v: JSValue) -> bool { +pub unsafe fn JS_IsUninitialized(v: JSValue) -> ::std::os::raw::c_int { JS_IsUninitialized_real(v) } /// check if a JSValue is a String -pub unsafe fn JS_IsString(v: JSValue) -> bool { +pub unsafe fn JS_IsString(v: JSValue) -> ::std::os::raw::c_int { JS_IsString_real(v) } /// check if a JSValue is a Symbol -pub unsafe fn JS_IsSymbol(v: JSValue) -> bool { +pub unsafe fn JS_IsSymbol(v: JSValue) -> ::std::os::raw::c_int { JS_IsSymbol_real(v) } /// check if a JSValue is an Object -pub unsafe fn JS_IsObject(v: JSValue) -> bool { +pub unsafe fn JS_IsObject(v: JSValue) -> ::std::os::raw::c_int { JS_IsObject_real(v) } diff --git a/oden-js/src/context.rs b/oden-js/src/context.rs index b7b09239..2004fb65 100644 --- a/oden-js/src/context.rs +++ b/oden-js/src/context.rs @@ -182,7 +182,8 @@ impl ContextRef { where T: Into, { - self.check_exception(unsafe { sys::JS_NewBool(self.ctx, value.into()) }) + let b = if value.into() { 1 } else { 0 }; + self.check_exception(unsafe { sys::JS_NewBool(self.ctx, b) }) } /// Construct a new value that wraps a strongly-typed closure. diff --git a/oden-js/src/conversion/into.rs b/oden-js/src/conversion/into.rs index cff22a69..2e4960bf 100644 --- a/oden-js/src/conversion/into.rs +++ b/oden-js/src/conversion/into.rs @@ -77,7 +77,9 @@ impl TryIntoValue for f64 { impl TryIntoValue for bool { #[inline] fn try_into_value(self, ctx: &ContextRef) -> ValueResult { - ctx.new_bool(self) + let result = ctx.new_bool(self); + // eprintln!("{self} -> {result:?}"); + result } } diff --git a/oden-js/src/conversion/mod.rs b/oden-js/src/conversion/mod.rs index b95c0bc1..ae0c43d8 100644 --- a/oden-js/src/conversion/mod.rs +++ b/oden-js/src/conversion/mod.rs @@ -6,3 +6,26 @@ pub use from::*; mod function; pub use function::*; + +#[cfg(test)] +mod tests { + use super::*; + use crate::{Context, ContextRef, Runtime}; + + fn check_round_trip(ctx: &ContextRef, v: T) + where + T: TryIntoValue + TryFromValue + PartialEq + Clone + std::fmt::Debug, + { + let val = v.clone().try_into_value(ctx).expect("Could not make value"); + let new = T::try_from_value(&val, ctx).expect("Could not unwrap value"); + assert_eq!(v, new); + } + + #[test] + fn round_trip() { + let ctx = Context::new(Runtime::new()); + check_round_trip(&ctx, true); + check_round_trip(&ctx, false); + check_round_trip(&ctx, 12); + } +}