Skip to content

Commit cc7467c

Browse files
committed
Preparing for the migration of modules
1 parent f3a20a3 commit cc7467c

File tree

14 files changed

+2165
-1458
lines changed

14 files changed

+2165
-1458
lines changed

src/js_array.rs

Lines changed: 644 additions & 499 deletions
Large diffs are not rendered by default.

src/js_assert.rs

Lines changed: 23 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -2,19 +2,25 @@ use crate::core::{Expr, JSObjectDataPtr, Value};
22
use crate::core::{evaluate_expr, evaluate_statements, new_js_object_data, obj_set_key_value, prepare_function_call_env};
33
use crate::error::JSError;
44
use crate::unicode::utf16_to_utf8;
5+
use gc_arena::Mutation as MutationContext;
56

67
/// Handle assert object method calls
7-
pub fn handle_assert_method(method: &str, args: &[Expr], env: &JSObjectDataPtr) -> Result<Value, JSError> {
8+
pub fn handle_assert_method<'gc>(
9+
mc: &MutationContext<'gc>,
10+
method: &str,
11+
args: &[Expr],
12+
env: &JSObjectDataPtr<'gc>,
13+
) -> Result<Value<'gc>, JSError> {
814
match method {
915
"sameValue" => {
1016
if args.len() < 2 || args.len() > 3 {
1117
return Err(raise_eval_error!("assert.sameValue requires 2 or 3 arguments"));
1218
}
1319

14-
let actual = evaluate_expr(env, &args[0])?;
15-
let expected = evaluate_expr(env, &args[1])?;
20+
let actual = evaluate_expr(mc, env, &args[0])?;
21+
let expected = evaluate_expr(mc, env, &args[1])?;
1622
let message = if args.len() == 3 {
17-
let message_val = evaluate_expr(env, &args[2])?;
23+
let message_val = evaluate_expr(mc, env, &args[2])?;
1824
match message_val {
1925
Value::String(s) => utf16_to_utf8(&s),
2026
_ => "assert.sameValue failed".to_string(),
@@ -43,10 +49,10 @@ pub fn handle_assert_method(method: &str, args: &[Expr], env: &JSObjectDataPtr)
4349
return Err(raise_eval_error!("assert.notSameValue requires 2 or 3 arguments"));
4450
}
4551

46-
let actual = evaluate_expr(env, &args[0])?;
47-
let expected = evaluate_expr(env, &args[1])?;
52+
let actual = evaluate_expr(mc, env, &args[0])?;
53+
let expected = evaluate_expr(mc, env, &args[1])?;
4854
let message = if args.len() == 3 {
49-
let message_val = evaluate_expr(env, &args[2])?;
55+
let message_val = evaluate_expr(mc, env, &args[2])?;
5056
match message_val {
5157
Value::String(s) => utf16_to_utf8(&s),
5258
_ => "assert.notSameValue failed".to_string(),
@@ -66,8 +72,13 @@ pub fn handle_assert_method(method: &str, args: &[Expr], env: &JSObjectDataPtr)
6672

6773
// If values are the same, this assertion fails — throw a plain error object
6874
if equal {
69-
let err_obj = new_js_object_data();
70-
obj_set_key_value(&err_obj, &"message".into(), Value::String(message.encode_utf16().collect()))?;
75+
let err_obj = new_js_object_data(mc);
76+
obj_set_key_value(
77+
mc,
78+
&err_obj,
79+
&"message".into(),
80+
Value::String(crate::unicode::utf8_to_utf16(&message)),
81+
)?;
7182
return Err(raise_throw_error!(Value::Object(err_obj)));
7283
}
7384

@@ -81,13 +92,13 @@ pub fn handle_assert_method(method: &str, args: &[Expr], env: &JSObjectDataPtr)
8192

8293
// We only care that calling the provided function throws.
8394
// Evaluate the second arg (the function) and execute its body.
84-
let func_val = evaluate_expr(env, &args[1])?;
95+
let func_val = evaluate_expr(mc, env, &args[1])?;
8596
match func_val {
8697
Value::Closure(data) => {
8798
let body = &data.body;
8899
let captured_env = &data.env;
89-
let func_env = prepare_function_call_env(Some(captured_env), None, None, &[], None, Some(env))?;
90-
match evaluate_statements(&func_env, body) {
100+
let func_env = prepare_function_call_env(mc, Some(captured_env), None, None, &[], None, Some(env))?;
101+
match evaluate_statements(mc, &func_env, body) {
91102
Ok(_) => Err(raise_eval_error!("assert.throws expected function to throw a value")),
92103
Err(_) => Ok(Value::Undefined),
93104
}

src/js_console.rs

Lines changed: 44 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -6,28 +6,34 @@ use crate::core::{
66
use crate::error::JSError;
77
use crate::js_promise;
88
use crate::unicode::utf16_to_utf8;
9+
use gc_arena::Mutation as MutationContext;
910
use std::cell::RefCell;
1011
use std::collections::HashSet;
1112
use std::rc::Rc;
1213

1314
/// Create the console object with logging functions
14-
pub fn make_console_object() -> Result<JSObjectDataPtr, JSError> {
15-
let console_obj = new_js_object_data();
16-
obj_set_key_value(&console_obj, &"log".into(), Value::Function("console.log".to_string()))?;
15+
pub fn make_console_object<'gc>(mc: &MutationContext<'gc>) -> Result<JSObjectDataPtr<'gc>, JSError> {
16+
let console_obj = new_js_object_data(mc);
17+
obj_set_key_value(mc, &console_obj, &"log".into(), Value::Function("console.log".to_string()))?;
1718
// Provide `console.error` as an alias to `console.log` for now
18-
obj_set_key_value(&console_obj, &"error".into(), Value::Function("console.error".to_string()))?;
19+
obj_set_key_value(mc, &console_obj, &"error".into(), Value::Function("console.error".to_string()))?;
1920
Ok(console_obj)
2021
}
2122

22-
fn format_console_value(val: &Value, env: &JSObjectDataPtr) -> Result<String, JSError> {
23+
fn format_console_value<'gc>(
24+
mc: &MutationContext<'gc>, // added mc
25+
val: &Value<'gc>,
26+
env: &JSObjectDataPtr<'gc>,
27+
) -> Result<String, JSError> {
2328
let mut seen = HashSet::new();
24-
format_value_pretty(val, env, 0, &mut seen, false)
29+
format_value_pretty(mc, val, env, 0, &mut seen, false)
2530
}
2631

27-
fn format_value_pretty(
28-
val: &Value,
29-
env: &JSObjectDataPtr,
30-
_depth: usize,
32+
fn format_value_pretty<'gc>(
33+
mc: &MutationContext<'gc>,
34+
val: &Value<'gc>,
35+
env: &JSObjectDataPtr<'gc>,
36+
depth: usize,
3137
seen: &mut HashSet<*const RefCell<crate::core::JSObjectData>>,
3238
quote_strings: bool,
3339
) -> Result<String, JSError> {
@@ -47,13 +53,13 @@ fn format_value_pretty(
4753
Value::Object(obj) => {
4854
// If this object is a Promise wrapper (stores inner promise under "__promise"),
4955
// print it compactly like Node: `Promise { <pending> }` and avoid listing internal helpers.
50-
if let Ok(Some(inner_rc)) = obj_get_key_value(obj, &"__promise".into()) {
56+
if let Ok(Some(inner_rc)) = obj_get_key_value(mc, obj, &"__promise".into()) {
5157
if let Value::Promise(p_rc) = &*inner_rc.borrow() {
52-
return format_promise(p_rc, env, _depth, seen);
58+
return format_promise(mc, p_rc, env, depth, seen);
5359
}
5460
}
5561
// If object looks like an Error (has non-empty "stack" string), print the stack directly
56-
if let Ok(Some(stack_rc)) = obj_get_key_value(obj, &"stack".into()) {
62+
if let Ok(Some(stack_rc)) = obj_get_key_value(mc, obj, &"stack".into()) {
5763
if let Value::String(s) = &*stack_rc.borrow() {
5864
let s_utf8 = crate::unicode::utf16_to_utf8(s);
5965
if !s_utf8.is_empty() {
@@ -71,20 +77,20 @@ fn format_value_pretty(
7177
Ok(Value::String(s)) => Ok(crate::unicode::utf16_to_utf8(&s)),
7278
_ => Ok("[object Date]".to_string()),
7379
}
74-
} else if crate::js_array::is_array(obj) {
80+
} else if crate::js_array::is_array(mc, obj) {
7581
if seen.contains(&Rc::as_ptr(obj)) {
7682
return Ok("[Circular]".to_string());
7783
}
7884
seen.insert(Rc::as_ptr(obj));
7985

80-
let len = crate::js_array::get_array_length(obj).unwrap_or(0);
86+
let len = crate::js_array::get_array_length(mc, obj).unwrap_or(0);
8187
let mut s = String::from("[");
8288
for i in 0..len {
8389
if i > 0 {
8490
s.push_str(", ");
8591
}
86-
if let Some(val_rc) = obj_get_key_value(obj, &i.to_string().into())? {
87-
let val_str = format_value_pretty(&val_rc.borrow(), env, _depth + 1, seen, true)?;
92+
if let Some(val_rc) = obj_get_key_value(mc, obj, &i.to_string().into())? {
93+
let val_str = format_value_pretty(mc, &val_rc.borrow(), env, depth + 1, seen, true)?;
8894
s.push_str(&val_str);
8995
} else if i == len - 1 {
9096
s.push(',');
@@ -95,7 +101,7 @@ fn format_value_pretty(
95101
Ok(s)
96102
} else {
97103
// Check for boxed primitive
98-
if let Some(val_rc) = obj_get_key_value(obj, &"__value__".into())? {
104+
if let Some(val_rc) = obj_get_key_value(mc, obj, &"__value__".into())? {
99105
let val = val_rc.borrow();
100106
match *val {
101107
Value::Boolean(b) => return Ok(format!("[Boolean: {}]", b)),
@@ -114,7 +120,7 @@ fn format_value_pretty(
114120

115121
// Try to get class name
116122
let mut class_name = String::new();
117-
if let Some(proto_rc) = obj.borrow().prototype.clone().and_then(|w| w.upgrade()) {
123+
if let Some(proto_rc) = obj.borrow().prototype.clone() {
118124
if let Some(ctor_val_rc) = proto_rc
119125
.borrow()
120126
.properties
@@ -170,7 +176,7 @@ fn format_value_pretty(
170176
}
171177

172178
s.push_str(": ");
173-
let val_str = format_value_pretty(&val_rc.borrow(), env, _depth + 1, seen, true)?;
179+
let val_str = format_value_pretty(mc, &val_rc.borrow(), env, depth + 1, seen, true)?;
174180
s.push_str(&val_str);
175181
}
176182
s.push('}');
@@ -234,28 +240,34 @@ fn format_value_pretty(
234240
}
235241

236242
// Helper to format a Promise (or an Rc<RefCell<JSPromise>>) in Node-like style.
237-
fn format_promise(
238-
p_rc: &Rc<RefCell<crate::js_promise::JSPromise>>,
239-
env: &JSObjectDataPtr,
240-
_depth: usize,
243+
fn format_promise<'gc>(
244+
mc: &MutationContext<'gc>,
245+
p_rc: &Rc<RefCell<crate::js_promise::JSPromise<'gc>>>,
246+
env: &JSObjectDataPtr<'gc>,
247+
depth: usize,
241248
seen: &mut HashSet<*const RefCell<crate::core::JSObjectData>>,
242249
) -> Result<String, JSError> {
243250
let p = p_rc.borrow();
244251
match &p.state {
245252
crate::js_promise::PromiseState::Pending => Ok("Promise { <pending> }".to_string()),
246253
crate::js_promise::PromiseState::Fulfilled(val) => {
247-
let inner = format_value_pretty(val, env, _depth + 1, seen, false)?;
254+
let inner = format_value_pretty(mc, val, env, depth + 1, seen, false)?;
248255
Ok(format!("Promise {{ {} }}", inner))
249256
}
250257
crate::js_promise::PromiseState::Rejected(val) => {
251-
let inner = format_value_pretty(val, env, _depth + 1, seen, false)?;
258+
let inner = format_value_pretty(mc, val, env, depth + 1, seen, false)?;
252259
Ok(format!("Promise {{ <rejected> {} }}", inner))
253260
}
254261
}
255262
}
256263

257264
/// Handle console object method calls
258-
pub fn handle_console_method(method: &str, args: &[Expr], env: &JSObjectDataPtr) -> Result<Value, JSError> {
265+
pub fn handle_console_method<'gc>(
266+
mc: &MutationContext<'gc>, // added mc
267+
method: &str,
268+
args: &[Expr],
269+
env: &JSObjectDataPtr<'gc>,
270+
) -> Result<Value<'gc>, JSError> {
259271
match method {
260272
"log" | "error" => {
261273
// Instrument: record current tick and task-queue length when console.log is invoked
@@ -267,7 +279,7 @@ pub fn handle_console_method(method: &str, args: &[Expr], env: &JSObjectDataPtr)
267279

268280
let mut values = Vec::new();
269281
for arg in args {
270-
values.push(evaluate_expr(env, arg)?);
282+
values.push(evaluate_expr(mc, env, arg)?);
271283
}
272284

273285
if values.is_empty() {
@@ -295,7 +307,7 @@ pub fn handle_console_method(method: &str, args: &[Expr], env: &JSObjectDataPtr)
295307
if arg_idx < values.len() {
296308
let val = &values[arg_idx];
297309
match next_char {
298-
's' => output.push_str(&format_console_value(val, env)?),
310+
's' => output.push_str(&format_console_value(mc, val, env)?),
299311
'd' | 'i' => {
300312
if let Value::Number(n) = val {
301313
output.push_str(&format!("{:.0}", n));
@@ -311,7 +323,7 @@ pub fn handle_console_method(method: &str, args: &[Expr], env: &JSObjectDataPtr)
311323
}
312324
}
313325
'o' | 'O' => {
314-
output.push_str(&format_console_value(val, env)?);
326+
output.push_str(&format_console_value(mc, val, env)?);
315327
}
316328
'c' => {
317329
// Ignore CSS
@@ -343,7 +355,7 @@ pub fn handle_console_method(method: &str, args: &[Expr], env: &JSObjectDataPtr)
343355

344356
if !formatted {
345357
// Just print first arg
346-
output.push_str(&format_console_value(&values[0], env)?);
358+
output.push_str(&format_console_value(mc, &values[0], env)?);
347359
arg_idx = 0;
348360
}
349361

@@ -352,7 +364,7 @@ pub fn handle_console_method(method: &str, args: &[Expr], env: &JSObjectDataPtr)
352364
if !output.is_empty() {
353365
output.push(' ');
354366
}
355-
output.push_str(&format_console_value(values_i, env)?);
367+
output.push_str(&format_console_value(mc, values_i, env)?);
356368
}
357369

358370
println!("{}", output);

0 commit comments

Comments
 (0)