Skip to content

Commit 7fcf685

Browse files
committed
Refactor core statement structures and optimize evaluation stack usage
- Refactor evaluate_expr by extracting large match arms into helper functions to reduce stack frame size - Refactor StatementKind to use boxed structs for complex statements (If, For, TryCatch) - Update BigInt, Number, and String constructors and to_primitive to accept MutationContext - Fix super property access to correctly invoke getters with the proper this receiver - Fix BigInt prototype chain and ensure Object prototype methods are non-enumerable - Update Array methods (sort, flatMap, findLast) to support closures wrapped in objects - Preserve is_arrow flag in Function.prototype.bind - Update generator yield replacement logic to match new statement structures
1 parent 208e22d commit 7fcf685

File tree

16 files changed

+3831
-1566
lines changed

16 files changed

+3831
-1566
lines changed

src/core/eval.rs

Lines changed: 2598 additions & 1109 deletions
Large diffs are not rendered by default.

src/core/gc.rs

Lines changed: 50 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,9 @@ pub fn trace_expr<'gc, T: GcTrace<'gc>>(context: &mut T, expr: &Expr) {
88
match d {
99
DestructuringElement::Variable(_, Some(e)) => trace_expr(cc, e),
1010
DestructuringElement::Property(_, inner) => trace_destructuring(cc, inner),
11+
DestructuringElement::Variable(_, None) => {}
12+
DestructuringElement::Rest(_) => {}
13+
DestructuringElement::Empty => {}
1114
DestructuringElement::NestedArray(arr) => {
1215
for a in arr {
1316
trace_destructuring(cc, a);
@@ -18,7 +21,6 @@ pub fn trace_expr<'gc, T: GcTrace<'gc>>(context: &mut T, expr: &Expr) {
1821
trace_destructuring(cc, e);
1922
}
2023
}
21-
_ => todo!(),
2224
}
2325
}
2426

@@ -70,12 +72,12 @@ pub fn trace_expr<'gc, T: GcTrace<'gc>>(context: &mut T, expr: &Expr) {
7072
trace_stmt(context, stmt);
7173
}
7274
}
73-
_ => todo!(),
75+
_ => {}
7476
}
7577
}
7678

7779
pub fn trace_stmt<'gc, T: GcTrace<'gc>>(context: &mut T, stmt: &Statement) {
78-
match &stmt.kind {
80+
match &*stmt.kind {
7981
StatementKind::Expr(e) => trace_expr(context, e),
8082
StatementKind::Let(decls) | StatementKind::Var(decls) => {
8183
for (_, e_opt) in decls {
@@ -102,12 +104,13 @@ pub fn trace_stmt<'gc, T: GcTrace<'gc>>(context: &mut T, stmt: &Statement) {
102104
trace_stmt(context, s);
103105
}
104106
}
105-
StatementKind::If(c, t, e_opt) => {
106-
trace_expr(context, c);
107-
for s in t {
107+
StatementKind::If(if_stmt) => {
108+
let if_stmt = if_stmt.as_ref();
109+
trace_expr(context, &if_stmt.condition);
110+
for s in &if_stmt.then_body {
108111
trace_stmt(context, s);
109112
}
110-
if let Some(e) = e_opt {
113+
if let Some(e) = &if_stmt.else_body {
111114
for s in e {
112115
trace_stmt(context, s);
113116
}
@@ -118,21 +121,56 @@ pub fn trace_stmt<'gc, T: GcTrace<'gc>>(context: &mut T, stmt: &Statement) {
118121
trace_stmt(context, s);
119122
}
120123
}
121-
StatementKind::TryCatch(try_body, _, catch_body, finally_body) => {
122-
for s in try_body {
124+
StatementKind::TryCatch(tc_stmt) => {
125+
let tc_stmt = tc_stmt.as_ref();
126+
for s in &tc_stmt.try_body {
123127
trace_stmt(context, s);
124128
}
125-
if let Some(stmts) = catch_body {
129+
if let Some(stmts) = &tc_stmt.catch_body {
126130
for s in stmts {
127131
trace_stmt(context, s);
128132
}
129133
}
130-
if let Some(stmts) = finally_body {
134+
if let Some(stmts) = &tc_stmt.finally_body {
131135
for s in stmts {
132136
trace_stmt(context, s);
133137
}
134138
}
135139
}
136-
_ => todo!(),
140+
StatementKind::For(for_stmt) => {
141+
let for_stmt = for_stmt.as_ref();
142+
if let Some(init) = &for_stmt.init {
143+
trace_stmt(context, init);
144+
}
145+
if let Some(test) = &for_stmt.test {
146+
trace_expr(context, test);
147+
}
148+
if let Some(update) = &for_stmt.update {
149+
trace_stmt(context, update);
150+
}
151+
for s in &for_stmt.body {
152+
trace_stmt(context, s);
153+
}
154+
}
155+
StatementKind::Switch(sw_stmt) => {
156+
let sw_stmt = sw_stmt.as_ref();
157+
trace_expr(context, &sw_stmt.expr);
158+
for case in &sw_stmt.cases {
159+
match case {
160+
crate::core::SwitchCase::Case(e, stmts) => {
161+
trace_expr(context, e);
162+
for s in stmts {
163+
trace_stmt(context, s);
164+
}
165+
}
166+
crate::core::SwitchCase::Default(stmts) => {
167+
for s in stmts {
168+
trace_stmt(context, s);
169+
}
170+
}
171+
}
172+
}
173+
}
174+
_ => {}
137175
}
138176
}

src/core/mod.rs

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -90,6 +90,16 @@ pub fn initialize_global_constructors<'gc>(mc: &MutationContext<'gc>, env: &JSOb
9090
env_set(mc, env, "Infinity", Value::Number(f64::INFINITY))?;
9191
env_set(mc, env, "eval", Value::Function("eval".to_string()))?;
9292

93+
// Expose common global functions as callables
94+
env_set(mc, env, "parseInt", Value::Function("parseInt".to_string()))?;
95+
env_set(mc, env, "parseFloat", Value::Function("parseFloat".to_string()))?;
96+
env_set(mc, env, "isNaN", Value::Function("isNaN".to_string()))?;
97+
env_set(mc, env, "isFinite", Value::Function("isFinite".to_string()))?;
98+
env_set(mc, env, "encodeURI", Value::Function("encodeURI".to_string()))?;
99+
env_set(mc, env, "decodeURI", Value::Function("decodeURI".to_string()))?;
100+
env_set(mc, env, "encodeURIComponent", Value::Function("encodeURIComponent".to_string()))?;
101+
env_set(mc, env, "decodeURIComponent", Value::Function("decodeURIComponent".to_string()))?;
102+
93103
#[cfg(feature = "os")]
94104
crate::js_os::initialize_os_module(mc, env)?;
95105

@@ -201,7 +211,17 @@ pub fn set_internal_prototype_from_constructor<'gc>(
201211
) -> Result<(), JSError> {
202212
if let Some(proto_obj) = get_constructor_prototype(mc, env, ctor_name)? {
203213
// set internal prototype pointer (store Weak to avoid cycles)
214+
log::trace!("setting prototype for ctor='{}' proto_obj={:p}", ctor_name, Gc::as_ptr(proto_obj));
204215
obj.borrow_mut(mc).prototype = Some(proto_obj.clone());
216+
// Also set the `__proto__` own property so `obj.__proto__` accesses match expectations
217+
match obj_set_key_value(mc, obj, &"__proto__".into(), Value::Object(proto_obj.clone())) {
218+
Ok(_) => {
219+
// __proto__ should be non-enumerable
220+
obj.borrow_mut(mc).set_non_enumerable(PropertyKey::from("__proto__"));
221+
log::trace!("set_internal_prototype_from_constructor: set __proto__ own property");
222+
}
223+
Err(e) => log::trace!("set_internal_prototype_from_constructor: failed to set __proto__: {:?}", e),
224+
}
205225
}
206226
Ok(())
207227
}

0 commit comments

Comments
 (0)