Skip to content

Commit 10f0cac

Browse files
committed
fix(serde_v8): serialize objects with numeric keys correctly
Fixes: #11502 Signed-off-by: Darshan Sen <[email protected]>
1 parent d7b27ed commit 10f0cac

File tree

3 files changed

+113
-2
lines changed

3 files changed

+113
-2
lines changed

core/runtime.rs

Lines changed: 84 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3216,6 +3216,90 @@ assertEquals(1, notify_return_value);
32163216
runtime.run_event_loop(false).await.unwrap();
32173217
}
32183218

3219+
#[tokio::test]
3220+
async fn test_sync_op_serialize_object_with_numbers_as_keys() {
3221+
#[op]
3222+
fn op_sync_serialize_object_with_numbers_as_keys(
3223+
value: serde_json::Value,
3224+
) -> Result<(), Error> {
3225+
assert_eq!(
3226+
value.to_string(),
3227+
r#"{"lines":{"100":{"unit":"m"},"200":{"unit":"cm"}}}"#
3228+
);
3229+
Ok(())
3230+
}
3231+
3232+
let extension = Extension::builder()
3233+
.ops(vec![op_sync_serialize_object_with_numbers_as_keys::decl()])
3234+
.build();
3235+
3236+
let mut runtime = JsRuntime::new(RuntimeOptions {
3237+
extensions: vec![extension],
3238+
..Default::default()
3239+
});
3240+
3241+
runtime
3242+
.execute_script(
3243+
"op_sync_serialize_object_with_numbers_as_keys.js",
3244+
r#"
3245+
Deno.core.ops.op_sync_serialize_object_with_numbers_as_keys({
3246+
lines: {
3247+
100: {
3248+
unit: "m"
3249+
},
3250+
200: {
3251+
unit: "cm"
3252+
}
3253+
}
3254+
})
3255+
"#,
3256+
)
3257+
.unwrap();
3258+
runtime.run_event_loop(false).await.unwrap();
3259+
}
3260+
3261+
#[tokio::test]
3262+
async fn test_async_op_serialize_object_with_numbers_as_keys() {
3263+
#[op]
3264+
async fn op_async_serialize_object_with_numbers_as_keys(
3265+
value: serde_json::Value,
3266+
) -> Result<(), Error> {
3267+
assert_eq!(
3268+
value.to_string(),
3269+
r#"{"lines":{"100":{"unit":"m"},"200":{"unit":"cm"}}}"#
3270+
);
3271+
Ok(())
3272+
}
3273+
3274+
let extension = Extension::builder()
3275+
.ops(vec![op_async_serialize_object_with_numbers_as_keys::decl()])
3276+
.build();
3277+
3278+
let mut runtime = JsRuntime::new(RuntimeOptions {
3279+
extensions: vec![extension],
3280+
..Default::default()
3281+
});
3282+
3283+
runtime
3284+
.execute_script(
3285+
"op_async_serialize_object_with_numbers_as_keys.js",
3286+
r#"
3287+
Deno.core.opAsync('op_async_serialize_object_with_numbers_as_keys', {
3288+
lines: {
3289+
100: {
3290+
unit: "m"
3291+
},
3292+
200: {
3293+
unit: "cm"
3294+
}
3295+
}
3296+
})
3297+
"#,
3298+
)
3299+
.unwrap();
3300+
runtime.run_event_loop(false).await.unwrap();
3301+
}
3302+
32193303
#[tokio::test]
32203304
async fn test_set_macrotask_callback_set_next_tick_callback() {
32213305
#[op]

serde_v8/de.rs

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -325,8 +325,12 @@ impl<'de, 'a, 'b, 's, 'x> de::Deserializer<'de>
325325
};
326326
visitor.visit_map(map)
327327
} else {
328-
let prop_names =
329-
obj.get_own_property_names(self.scope, Default::default());
328+
let prop_names = obj.get_own_property_names(
329+
self.scope,
330+
v8::GetPropertyNamesArgsBuilder::new()
331+
.key_conversion(v8::KeyConversionMode::ConvertToString)
332+
.build(),
333+
);
330334
let keys: Vec<magic::Value> = match prop_names {
331335
Some(names) => from_v8(self.scope, names.into()).unwrap(),
332336
None => vec![],

serde_v8/tests/de.rs

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -184,6 +184,29 @@ fn de_map() {
184184
})
185185
}
186186

187+
#[test]
188+
fn de_obj_with_numeric_keys() {
189+
dedo(
190+
r#"({
191+
lines: {
192+
100: {
193+
unit: "m"
194+
},
195+
200: {
196+
unit: "cm"
197+
}
198+
}
199+
})"#,
200+
|scope, v| {
201+
let json: serde_json::Value = serde_v8::from_v8(scope, v).unwrap();
202+
assert_eq!(
203+
json.to_string(),
204+
r#"{"lines":{"100":{"unit":"m"},"200":{"unit":"cm"}}}"#
205+
);
206+
},
207+
)
208+
}
209+
187210
#[test]
188211
fn de_string_or_buffer() {
189212
dedo("'hello'", |scope, v| {

0 commit comments

Comments
 (0)