mirror of https://github.com/boa-dev/boa.git
Paul Lancaster
5 years ago
committed by
GitHub
25 changed files with 756 additions and 69 deletions
@ -0,0 +1,16 @@ |
|||||||
|
use super::{Executable, Interpreter, InterpreterState}; |
||||||
|
use crate::{ |
||||||
|
builtins::value::{ResultValue, Value}, |
||||||
|
syntax::ast::node::Break, |
||||||
|
}; |
||||||
|
|
||||||
|
#[cfg(test)] |
||||||
|
mod tests; |
||||||
|
|
||||||
|
impl Executable for Break { |
||||||
|
fn run(&self, interpreter: &mut Interpreter) -> ResultValue { |
||||||
|
interpreter.set_current_state(InterpreterState::Break(self.label().map(String::from))); |
||||||
|
|
||||||
|
Ok(Value::undefined()) |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,17 @@ |
|||||||
|
use super::{Interpreter, InterpreterState}; |
||||||
|
use crate::{exec::Executable, syntax::ast::node::Break, Realm}; |
||||||
|
|
||||||
|
#[test] |
||||||
|
fn check_post_state() { |
||||||
|
let realm = Realm::create(); |
||||||
|
let mut engine = Interpreter::new(realm); |
||||||
|
|
||||||
|
let brk: Break = Break::new("label"); |
||||||
|
|
||||||
|
brk.run(&mut engine).unwrap(); |
||||||
|
|
||||||
|
assert_eq!( |
||||||
|
engine.get_current_state(), |
||||||
|
&InterpreterState::Break(Some("label".to_string())) |
||||||
|
); |
||||||
|
} |
@ -0,0 +1,101 @@ |
|||||||
|
use crate::exec; |
||||||
|
|
||||||
|
#[test] |
||||||
|
fn while_loop_late_break() { |
||||||
|
// Ordering with statement before the break.
|
||||||
|
let scenario = r#" |
||||||
|
let a = 1; |
||||||
|
while (a < 5) { |
||||||
|
a++; |
||||||
|
if (a == 3) { |
||||||
|
break; |
||||||
|
} |
||||||
|
} |
||||||
|
a; |
||||||
|
"#; |
||||||
|
|
||||||
|
assert_eq!(&exec(scenario), "3"); |
||||||
|
} |
||||||
|
|
||||||
|
#[test] |
||||||
|
fn while_loop_early_break() { |
||||||
|
// Ordering with statements after the break.
|
||||||
|
let scenario = r#" |
||||||
|
let a = 1; |
||||||
|
while (a < 5) { |
||||||
|
if (a == 3) { |
||||||
|
break; |
||||||
|
} |
||||||
|
a++; |
||||||
|
} |
||||||
|
a; |
||||||
|
"#; |
||||||
|
|
||||||
|
assert_eq!(&exec(scenario), "3"); |
||||||
|
} |
||||||
|
|
||||||
|
#[test] |
||||||
|
fn for_loop_break() { |
||||||
|
let scenario = r#" |
||||||
|
let a = 1; |
||||||
|
for (; a < 5; a++) { |
||||||
|
if (a == 3) { |
||||||
|
break; |
||||||
|
} |
||||||
|
} |
||||||
|
a; |
||||||
|
"#; |
||||||
|
|
||||||
|
assert_eq!(&exec(scenario), "3"); |
||||||
|
} |
||||||
|
|
||||||
|
#[test] |
||||||
|
fn for_loop_return() { |
||||||
|
let scenario = r#" |
||||||
|
function foo() { |
||||||
|
for (let a = 1; a < 5; a++) { |
||||||
|
if (a == 3) { |
||||||
|
return a; |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
foo(); |
||||||
|
"#; |
||||||
|
|
||||||
|
assert_eq!(&exec(scenario), "3"); |
||||||
|
} |
||||||
|
|
||||||
|
#[test] |
||||||
|
fn do_loop_late_break() { |
||||||
|
// Ordering with statement before the break.
|
||||||
|
let scenario = r#" |
||||||
|
let a = 1; |
||||||
|
do { |
||||||
|
a++; |
||||||
|
if (a == 3) { |
||||||
|
break; |
||||||
|
} |
||||||
|
} while (a < 5); |
||||||
|
a; |
||||||
|
"#; |
||||||
|
|
||||||
|
assert_eq!(&exec(scenario), "3"); |
||||||
|
} |
||||||
|
|
||||||
|
#[test] |
||||||
|
fn do_loop_early_break() { |
||||||
|
// Ordering with statements after the break.
|
||||||
|
let scenario = r#" |
||||||
|
let a = 1; |
||||||
|
do { |
||||||
|
if (a == 3) { |
||||||
|
break; |
||||||
|
} |
||||||
|
a++; |
||||||
|
} while (a < 5); |
||||||
|
a; |
||||||
|
"#; |
||||||
|
|
||||||
|
assert_eq!(&exec(scenario), "3"); |
||||||
|
} |
@ -0,0 +1,200 @@ |
|||||||
|
use crate::exec; |
||||||
|
|
||||||
|
#[test] |
||||||
|
fn single_case_switch() { |
||||||
|
let scenario = r#" |
||||||
|
let a = 10; |
||||||
|
switch (a) { |
||||||
|
case 10: |
||||||
|
a = 20; |
||||||
|
break; |
||||||
|
} |
||||||
|
|
||||||
|
a; |
||||||
|
"#; |
||||||
|
assert_eq!(&exec(scenario), "20"); |
||||||
|
} |
||||||
|
|
||||||
|
#[test] |
||||||
|
fn no_cases_switch() { |
||||||
|
let scenario = r#" |
||||||
|
let a = 10; |
||||||
|
switch (a) { |
||||||
|
} |
||||||
|
|
||||||
|
a; |
||||||
|
"#; |
||||||
|
assert_eq!(&exec(scenario), "10"); |
||||||
|
} |
||||||
|
|
||||||
|
#[test] |
||||||
|
fn no_true_case_switch() { |
||||||
|
let scenario = r#" |
||||||
|
let a = 10; |
||||||
|
switch (a) { |
||||||
|
case 5: |
||||||
|
a = 15; |
||||||
|
break; |
||||||
|
} |
||||||
|
|
||||||
|
a; |
||||||
|
"#; |
||||||
|
assert_eq!(&exec(scenario), "10"); |
||||||
|
} |
||||||
|
|
||||||
|
#[test] |
||||||
|
fn two_case_switch() { |
||||||
|
let scenario = r#" |
||||||
|
let a = 10; |
||||||
|
switch (a) { |
||||||
|
case 5: |
||||||
|
a = 15; |
||||||
|
break; |
||||||
|
case 10: |
||||||
|
a = 20; |
||||||
|
break; |
||||||
|
} |
||||||
|
|
||||||
|
a; |
||||||
|
"#; |
||||||
|
assert_eq!(&exec(scenario), "20"); |
||||||
|
} |
||||||
|
|
||||||
|
#[test] |
||||||
|
fn two_case_no_break_switch() { |
||||||
|
let scenario = r#" |
||||||
|
let a = 10; |
||||||
|
let b = 10; |
||||||
|
|
||||||
|
switch (a) { |
||||||
|
case 10: |
||||||
|
a = 150; |
||||||
|
case 20: |
||||||
|
b = 150; |
||||||
|
break; |
||||||
|
} |
||||||
|
|
||||||
|
a + b; |
||||||
|
"#; |
||||||
|
assert_eq!(&exec(scenario), "300"); |
||||||
|
} |
||||||
|
|
||||||
|
#[test] |
||||||
|
fn three_case_partial_fallthrough() { |
||||||
|
let scenario = r#" |
||||||
|
let a = 10; |
||||||
|
let b = 10; |
||||||
|
|
||||||
|
switch (a) { |
||||||
|
case 10: |
||||||
|
a = 150; |
||||||
|
case 20: |
||||||
|
b = 150; |
||||||
|
break; |
||||||
|
case 15: |
||||||
|
b = 1000; |
||||||
|
break; |
||||||
|
} |
||||||
|
|
||||||
|
a + b; |
||||||
|
"#; |
||||||
|
assert_eq!(&exec(scenario), "300"); |
||||||
|
} |
||||||
|
|
||||||
|
#[test] |
||||||
|
fn default_taken_switch() { |
||||||
|
let scenario = r#" |
||||||
|
let a = 10; |
||||||
|
|
||||||
|
switch (a) { |
||||||
|
case 5: |
||||||
|
a = 150; |
||||||
|
break; |
||||||
|
default: |
||||||
|
a = 70; |
||||||
|
} |
||||||
|
|
||||||
|
a; |
||||||
|
"#; |
||||||
|
assert_eq!(&exec(scenario), "70"); |
||||||
|
} |
||||||
|
|
||||||
|
#[test] |
||||||
|
fn default_not_taken_switch() { |
||||||
|
let scenario = r#" |
||||||
|
let a = 5; |
||||||
|
|
||||||
|
switch (a) { |
||||||
|
case 5: |
||||||
|
a = 150; |
||||||
|
break; |
||||||
|
default: |
||||||
|
a = 70; |
||||||
|
} |
||||||
|
|
||||||
|
a; |
||||||
|
"#; |
||||||
|
assert_eq!(&exec(scenario), "150"); |
||||||
|
} |
||||||
|
|
||||||
|
#[test] |
||||||
|
fn string_switch() { |
||||||
|
let scenario = r#" |
||||||
|
let a = "hello"; |
||||||
|
|
||||||
|
switch (a) { |
||||||
|
case "hello": |
||||||
|
a = "world"; |
||||||
|
break; |
||||||
|
default: |
||||||
|
a = "hi"; |
||||||
|
} |
||||||
|
|
||||||
|
a; |
||||||
|
"#; |
||||||
|
assert_eq!(&exec(scenario), "world"); |
||||||
|
} |
||||||
|
|
||||||
|
#[test] |
||||||
|
fn bigger_switch_example() { |
||||||
|
let expected = ["Mon", "Tue", "Wed", "Thurs", "Fri", "Sat", "Sun"]; |
||||||
|
|
||||||
|
for (i, val) in expected.iter().enumerate() { |
||||||
|
let scenario = format!( |
||||||
|
r#" |
||||||
|
let a = {}; |
||||||
|
let b = "unknown"; |
||||||
|
|
||||||
|
switch (a) {{ |
||||||
|
case 0: |
||||||
|
b = "Mon"; |
||||||
|
break; |
||||||
|
case 1: |
||||||
|
b = "Tue"; |
||||||
|
break; |
||||||
|
case 2: |
||||||
|
b = "Wed"; |
||||||
|
break; |
||||||
|
case 3: |
||||||
|
b = "Thurs"; |
||||||
|
break; |
||||||
|
case 4: |
||||||
|
b = "Fri"; |
||||||
|
break; |
||||||
|
case 5: |
||||||
|
b = "Sat"; |
||||||
|
break; |
||||||
|
case 6: |
||||||
|
b = "Sun"; |
||||||
|
break;
|
||||||
|
}} |
||||||
|
|
||||||
|
b; |
||||||
|
|
||||||
|
"#, |
||||||
|
i |
||||||
|
); |
||||||
|
|
||||||
|
assert_eq!(&exec(&scenario), val); |
||||||
|
} |
||||||
|
} |
@ -1 +1,99 @@ |
|||||||
|
use crate::syntax::parser::tests::check_invalid; |
||||||
|
|
||||||
|
/// Checks parsing malformed switch with no closeblock.
|
||||||
|
#[test] |
||||||
|
fn check_switch_no_closeblock() { |
||||||
|
check_invalid( |
||||||
|
r#" |
||||||
|
let a = 10; |
||||||
|
switch (a) { |
||||||
|
case 10: |
||||||
|
a = 20; |
||||||
|
break; |
||||||
|
|
||||||
|
"#, |
||||||
|
); |
||||||
|
} |
||||||
|
|
||||||
|
/// Checks parsing malformed switch in which a case is started but not finished.
|
||||||
|
#[test] |
||||||
|
fn check_switch_case_unclosed() { |
||||||
|
check_invalid( |
||||||
|
r#" |
||||||
|
let a = 10; |
||||||
|
switch (a) { |
||||||
|
case 10: |
||||||
|
a = 20; |
||||||
|
|
||||||
|
"#, |
||||||
|
); |
||||||
|
} |
||||||
|
|
||||||
|
/// Checks parsing malformed switch with 2 defaults.
|
||||||
|
#[test] |
||||||
|
fn check_switch_two_default() { |
||||||
|
check_invalid( |
||||||
|
r#" |
||||||
|
let a = 10; |
||||||
|
switch (a) { |
||||||
|
default: |
||||||
|
a = 20; |
||||||
|
break; |
||||||
|
default: |
||||||
|
a = 30; |
||||||
|
break; |
||||||
|
} |
||||||
|
"#, |
||||||
|
); |
||||||
|
} |
||||||
|
|
||||||
|
/// Checks parsing malformed switch with no expression.
|
||||||
|
#[test] |
||||||
|
fn check_switch_no_expr() { |
||||||
|
check_invalid( |
||||||
|
r#" |
||||||
|
let a = 10; |
||||||
|
switch { |
||||||
|
default: |
||||||
|
a = 20; |
||||||
|
break; |
||||||
|
} |
||||||
|
"#, |
||||||
|
); |
||||||
|
} |
||||||
|
|
||||||
|
/// Checks parsing malformed switch with an unknown label.
|
||||||
|
#[test] |
||||||
|
fn check_switch_unknown_label() { |
||||||
|
check_invalid( |
||||||
|
r#" |
||||||
|
let a = 10; |
||||||
|
switch (a) { |
||||||
|
fake: |
||||||
|
a = 20; |
||||||
|
break; |
||||||
|
} |
||||||
|
"#, |
||||||
|
); |
||||||
|
} |
||||||
|
|
||||||
|
/// Checks parsing malformed switch with two defaults that are seperated by cases.
|
||||||
|
#[test] |
||||||
|
fn check_switch_seperated_defaults() { |
||||||
|
check_invalid( |
||||||
|
r#" |
||||||
|
let a = 10; |
||||||
|
switch (a) { |
||||||
|
default: |
||||||
|
a = 20; |
||||||
|
break; |
||||||
|
case 10: |
||||||
|
a = 60; |
||||||
|
break; |
||||||
|
default: |
||||||
|
a = 30; |
||||||
|
break; |
||||||
|
} |
||||||
|
"#, |
||||||
|
); |
||||||
|
} |
||||||
|
Loading…
Reference in new issue