Skip to content

Commit 90d8b16

Browse files
committed
fix: handle fractional numbers properly
1 parent 5751cd6 commit 90d8b16

File tree

2 files changed

+56
-2
lines changed

2 files changed

+56
-2
lines changed

js-sandbox/Cargo.toml

+2-1
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22

33
[package]
44
name = "js-sandbox-ios"
5-
version = "0.1.0"
5+
version = "0.1.1"
66
description = "Execute JavaScript code from Rust in a secure sandbox, and transport data to/from JS plug-ins."
77
repository = "https://github.com/Bromeon/js-sandbox"
88
documentation = "https://docs.rs/js-sandbox/0.2.0-rc.1"
@@ -16,3 +16,4 @@ js-sandbox-macros = { path = "../js-sandbox-macros", version = "=0.2.0-rc.1" }
1616
deno_core = "0.238.0"
1717
serde_json = "1.0.106"
1818
serde = { version = "1.0.188", features = ["derive"] }
19+
tracing = "0.1.40"

js-sandbox/src/script.rs

+54-1
Original file line numberDiff line numberDiff line change
@@ -200,13 +200,66 @@ impl Script {
200200
};
201201
let deserialized_value = serde_v8::from_v8::<serde_json::Value>(scope, func_res)
202202
.with_context(|| "Could not serialize func res")?;
203-
let result: CallResult<R> = serde_json::from_value(deserialized_value)?;
203+
let sanitized_value = Self::sanitize_number(deserialized_value)?;
204+
let result: CallResult<R> = serde_json::from_value(sanitized_value)?;
204205
match result {
205206
CallResult::Error { error } => Err(JsError::Runtime(AnyError::msg(error))),
206207
CallResult::Result(r) => Ok(r),
207208
}
208209
}
209210

211+
fn sanitize_number(value: serde_json::Value) -> Result<serde_json::Value, JsError> {
212+
match value {
213+
serde_json::Value::Number(number) => {
214+
if number.is_f64() {
215+
let f = number.as_f64().ok_or_else(|| {
216+
JsError::Runtime(AnyError::msg("Failed to convert number to f64"))
217+
})?;
218+
219+
if f.fract() == 0.0 {
220+
return Ok(serde_json::Value::Number(serde_json::Number::from(
221+
f as i64,
222+
)));
223+
}
224+
225+
Ok(serde_json::Value::Number(
226+
serde_json::Number::from_f64(f).ok_or_else(|| {
227+
JsError::Runtime(AnyError::msg("Failed to convert f64 to number"))
228+
})?,
229+
))
230+
} else if number.is_u64() {
231+
Ok(serde_json::Value::Number(
232+
number
233+
.as_i64()
234+
.ok_or_else(|| {
235+
JsError::Runtime(AnyError::msg("Failed to convert number to i64"))
236+
})?
237+
.into(),
238+
))
239+
} else if number.is_i64() {
240+
Ok(serde_json::Value::Number(number))
241+
} else {
242+
Err(JsError::Runtime(AnyError::msg("Failed to convert number")))
243+
}
244+
}
245+
serde_json::Value::Object(map) => {
246+
let mut new_map = serde_json::Map::new();
247+
for (key, value) in map {
248+
new_map.insert(key, Self::sanitize_number(value)?);
249+
}
250+
Ok(serde_json::Value::Object(new_map))
251+
}
252+
serde_json::Value::Array(vec) => {
253+
let mut new_vec = Vec::new();
254+
for value in vec {
255+
new_vec.push(Self::sanitize_number(value)?);
256+
}
257+
Ok(serde_json::Value::Array(new_vec))
258+
}
259+
_ => Ok(value),
260+
}
261+
}
262+
210263
pub fn bind_api<'a, A>(&'a mut self) -> A
211264
where
212265
A: JsApi<'a>,

0 commit comments

Comments
 (0)