Skip to content

Commit 0a87a88

Browse files
committed
Implement JSON object and integrate it into the engine
- Add js_json.rs with JSON.parse and JSON.stringify implementation. - Register JSON object in initialize_global_constructors. - Add dispatch logic for JSON methods in eval.rs. - Refactor array literal evaluation to use create_array to ensure correct array prototype and internal flags.
1 parent dd20e4a commit 0a87a88

File tree

4 files changed

+31
-21
lines changed

4 files changed

+31
-21
lines changed

src/core/eval.rs

Lines changed: 6 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,10 @@
11
#![allow(warnings)]
22

33
use crate::core::{Gc, GcCell, MutationContext};
4-
use crate::js_array::{handle_array_static_method, is_array};
4+
use crate::js_array::{create_array, handle_array_static_method, is_array, set_array_length};
55
use crate::js_bigint::bigint_constructor;
66
use crate::js_date::{handle_date_method, handle_date_static_method, is_date_object};
7+
use crate::js_json::handle_json_method;
78
use crate::js_number::{handle_number_instance_method, handle_number_prototype_method, handle_number_static_method, number_constructor};
89
use crate::js_string::{string_from_char_code, string_from_code_point, string_raw};
910
use crate::{
@@ -986,24 +987,15 @@ pub fn evaluate_expr<'gc>(mc: &MutationContext<'gc>, env: &JSObjectDataPtr<'gc>,
986987
Ok(Value::Object(obj))
987988
}
988989
Expr::Array(elements) => {
989-
let arr_obj = crate::core::new_js_object_data(mc);
990-
if let Ok(Value::Object(arr_ctor)) = evaluate_var(mc, env, "Array") {
991-
if let Some(proto_val) = obj_get_key_value(&arr_ctor, &"prototype".into())? {
992-
if let Value::Object(proto) = &*proto_val.borrow() {
993-
arr_obj.borrow_mut(mc).prototype = Some(*proto);
994-
}
995-
}
996-
}
990+
let arr_obj = create_array(mc, env)?;
997991

998-
let mut len = 0;
999992
for (i, elem_opt) in elements.iter().enumerate() {
1000993
if let Some(elem) = elem_opt {
1001994
let val = evaluate_expr(mc, env, elem)?;
1002995
obj_set_key_value(mc, &arr_obj, &i.to_string().into(), val)?;
1003996
}
1004-
len = i + 1;
1005997
}
1006-
obj_set_key_value(mc, &arr_obj, &"length".into(), Value::Number(len as f64))?;
998+
set_array_length(mc, &arr_obj, elements.len())?;
1007999
Ok(Value::Object(arr_obj))
10081000
}
10091001
Expr::Function(name, params, body) => {
@@ -1115,6 +1107,8 @@ pub fn evaluate_expr<'gc>(mc: &MutationContext<'gc>, env: &JSObjectDataPtr<'gc>,
11151107
Ok(handle_number_static_method(method, &eval_args).map_err(EvalError::Js)?)
11161108
} else if let Some(method) = name.strip_prefix("Math.") {
11171109
Ok(handle_math_call(mc, method, &eval_args, env).map_err(EvalError::Js)?)
1110+
} else if let Some(method) = name.strip_prefix("JSON.") {
1111+
Ok(handle_json_method(mc, method, &eval_args, env).map_err(EvalError::Js)?)
11181112
} else if let Some(method) = name.strip_prefix("Date.prototype.") {
11191113
if let Some(this_obj) = this_val {
11201114
Ok(handle_date_method(mc, &this_obj, method, &eval_args, env).map_err(EvalError::Js)?)

src/core/mod.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ use crate::js_array::initialize_array;
33
use crate::js_bigint::initialize_bigint;
44
use crate::js_console::initialize_console_object;
55
use crate::js_date::initialize_date;
6+
use crate::js_json::initialize_json;
67
use crate::js_math::initialize_math;
78
use crate::js_number::initialize_number_module;
89
use crate::js_regexp::initialize_regexp;
@@ -82,6 +83,7 @@ pub fn initialize_global_constructors<'gc>(mc: &MutationContext<'gc>, env: &JSOb
8283
// Initialize Date constructor and prototype
8384
initialize_date(mc, env)?;
8485
initialize_bigint(mc, env)?;
86+
initialize_json(mc, env)?;
8587

8688
env_set(mc, env, "undefined", Value::Undefined)?;
8789
env_set(mc, env, "NaN", Value::Number(f64::NAN))?;

src/js_json.rs

Lines changed: 22 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,19 +1,33 @@
1-
use crate::core::{Collect, Gc, GcCell, GcPtr, MutationContext, Trace};
2-
use crate::core::{Expr, JSObjectDataPtr, PropertyKey, Value, evaluate_expr, get_own_property, new_js_object_data, obj_set_key_value};
1+
use crate::core::MutationContext;
2+
use crate::core::{JSObjectDataPtr, PropertyKey, Value, env_set, get_own_property, new_js_object_data, obj_set_key_value};
33
use crate::error::JSError;
44
use crate::js_array::{get_array_length, is_array, set_array_length};
55
use crate::unicode::{utf8_to_utf16, utf16_to_utf8};
66

7+
pub fn initialize_json<'gc>(mc: &MutationContext<'gc>, env: &JSObjectDataPtr<'gc>) -> Result<(), JSError> {
8+
let json_obj = new_js_object_data(mc);
9+
10+
obj_set_key_value(mc, &json_obj, &"parse".into(), Value::Function("JSON.parse".to_string()))?;
11+
obj_set_key_value(mc, &json_obj, &"stringify".into(), Value::Function("JSON.stringify".to_string()))?;
12+
13+
// JSON object usually has [Symbol.toStringTag] = "JSON"
14+
// obj_set_key_value(mc, &json_obj, &crate::core::PropertyKey::from("Symbol.toStringTag"), Value::String(utf8_to_utf16("JSON")))?;
15+
// We can skip that for now if not strictly required, or add it if Symbol is supported.
16+
17+
env_set(mc, env, "JSON", Value::Object(json_obj))?;
18+
Ok(())
19+
}
20+
721
pub fn handle_json_method<'gc>(
822
mc: &MutationContext<'gc>,
923
method: &str,
10-
args: &[Expr],
24+
args: &[Value<'gc>],
1125
env: &JSObjectDataPtr<'gc>,
1226
) -> Result<Value<'gc>, JSError> {
1327
match method {
1428
"parse" => {
15-
if args.len() == 1 {
16-
let arg_val = evaluate_expr(mc, env, &args[0])?;
29+
if args.len() >= 1 {
30+
let arg_val = &args[0];
1731
match arg_val {
1832
Value::String(s) => {
1933
let json_str = utf16_to_utf8(&s);
@@ -29,9 +43,9 @@ pub fn handle_json_method<'gc>(
2943
}
3044
}
3145
"stringify" => {
32-
if args.len() == 1 {
33-
let arg_val = evaluate_expr(mc, env, &args[0])?;
34-
match js_value_to_json_value(mc, arg_val) {
46+
if args.len() >= 1 {
47+
let arg_val = &args[0];
48+
match js_value_to_json_value(mc, arg_val.clone()) {
3549
Some(json_value) => match serde_json::to_string(&json_value) {
3650
Ok(json_str) => {
3751
log::debug!("JSON.stringify produced: {}", json_str);

src/lib.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ pub(crate) mod js_console;
1111
pub(crate) mod js_date;
1212
// pub(crate) mod js_function;
1313
// pub(crate) mod js_generator;
14-
// pub(crate) mod js_json;
14+
pub(crate) mod js_json;
1515
// pub(crate) mod js_map;
1616
pub(crate) mod js_math;
1717
pub(crate) mod js_module;

0 commit comments

Comments
 (0)