diff --git a/boa/benches/exec.rs b/boa/benches/exec.rs index ff564aac0f..60de7dbe7b 100644 --- a/boa/benches/exec.rs +++ b/boa/benches/exec.rs @@ -26,30 +26,25 @@ fn symbol_creation(c: &mut Criterion) { }); } -// TODO: implement for loops. -// static FOR_LOOP: &str = r#" -// let a = 10; -// let b = "hello"; -// for (;;) { -// a += 5; +static FOR_LOOP: &str = r#" +let a = 10; +let b = "hello"; +for (;a > 100;) { + a += 5; -// if (a < 50) { -// b += "world"; -// } + if (a < 50) { + b += "world"; + } +} -// if (a > 100) { -// break; -// } -// } -// let c = a; -// let d = b; -// "#; +b +"#; -// fn for_loop_execution(c: &mut Criterion) { -// c.bench_function("For loop (Execution)", move |b| { -// b.iter(|| exec(black_box(FOR_LOOP))) -// }); -// } +fn for_loop_execution(c: &mut Criterion) { + c.bench_function("For loop (Execution)", move |b| { + b.iter(|| exec(black_box(FOR_LOOP))) + }); +} static FIBONACCI: &str = r#" let num = 12; @@ -74,7 +69,7 @@ criterion_group!( execution, create_realm, symbol_creation, - // for_loop_execution, + for_loop_execution, fibonacci ); criterion_main!(execution); diff --git a/boa/src/exec/mod.rs b/boa/src/exec/mod.rs index f3ed0040fb..ef11ee3613 100644 --- a/boa/src/exec/mod.rs +++ b/boa/src/exec/mod.rs @@ -173,6 +173,24 @@ impl Executor for Interpreter { } Ok(result) } + Node::ForLoop(ref init, ref cond, ref step, ref body) => { + if let Some(init) = init { + self.run(init)?; + } + + while match cond { + Some(cond) => self.run(cond)?.borrow().is_true(), + None => true, + } { + self.run(body)?; + + if let Some(step) = step { + self.run(step)?; + } + } + + Ok(Gc::new(ValueData::Undefined)) + } Node::If(ref cond, ref expr, None) => Ok(if self.run(cond)?.borrow().is_true() { self.run(expr)? } else { diff --git a/boa/src/exec/tests.rs b/boa/src/exec/tests.rs index 720cf8c563..8c5f57901d 100644 --- a/boa/src/exec/tests.rs +++ b/boa/src/exec/tests.rs @@ -304,6 +304,51 @@ fn test_do_while_post_inc() { assert_eq!(exec(with_post_incrementors), String::from("11")); } +#[test] +fn test_for_loop() { + let simple = r#" + const a = ['h', 'e', 'l', 'l', 'o']; + let b = ''; + for (let i = 0; i < a.length; i = i + 1) { + b = b + a[i]; + } + b + "#; + assert_eq!(exec(simple), String::from("hello")); + + let without_init_and_inc_step = r#" + let a = 0; + let i = 0; + for (;i < 10;) { + a = a + i; + i = i + 1; + } + + a + "#; + assert_eq!(exec(without_init_and_inc_step), String::from("45")); + + let body_should_not_execute_on_false_condition = r#" + let a = 0 + for (;false;) { + a = a + 1; + } + + a + "#; + assert_eq!( + exec(body_should_not_execute_on_false_condition), + String::from("0") + ); + + let inner_scope = r#" + for (let i = 0;false;) {} + + i + "#; + assert_eq!(exec(inner_scope), String::from("undefined")); +} + #[test] #[ignore] fn test_unary_pre() {