From 230b0f84bf923aa96bfad60e203e655e6dfbbf06 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andr=C3=A9=20Eriksson?= Date: Tue, 29 Oct 2024 09:04:12 +0100 Subject: [PATCH] runtimes/js: parse nulls in responses correctly --- runtimes/js/src/pvalue.rs | 32 ++++++++++++++++++++++++++++++-- 1 file changed, 30 insertions(+), 2 deletions(-) diff --git a/runtimes/js/src/pvalue.rs b/runtimes/js/src/pvalue.rs index 196087cebf..da606cb6f9 100644 --- a/runtimes/js/src/pvalue.rs +++ b/runtimes/js/src/pvalue.rs @@ -212,8 +212,8 @@ impl FromNapiValue for PVals { let mut map = PVals(PValues::new()); for key in JsObject::keys(&obj)?.into_iter() { - if let Some(val) = obj.get::<_, PVal>(&key)? { - map.0.insert(key, val.0); + if let Some(val) = obj_get_pval(env, napi_val, &key)? { + map.0.insert(key, val); } } @@ -279,3 +279,31 @@ fn timestamp_to_dt(millis: f64) -> chrono::DateTime { let ts = chrono::Utc.timestamp_opt(secs, nanos as u32); ts.unwrap().fixed_offset() } + +// This is an inlined version of JsObject::get that distinguishes between null and undefined. +fn obj_get_pval>( + env: sys::napi_env, + obj: sys::napi_value, + field: K, +) -> Result> { + let c_field = std::ffi::CString::new(field.as_ref())?; + + unsafe { + let mut ret = std::ptr::null_mut(); + + check_status!( + sys::napi_get_named_property(env, obj, c_field.as_ptr(), &mut ret), + "Failed to get property with field `{}`", + field.as_ref(), + )?; + + let ty = type_of!(env, ret)?; + + if ty == ValueType::Undefined { + return Ok(None); + } + + let pval = PVal::from_napi_value(env, ret)?; + Ok(Some(pval.0)) + } +}