javascript 0.1.13

A JavaScript engine implementation in Rust
Documentation
use javascript::*;

#[test]
fn duplicate_private_identifier_is_syntax_error() {
    let script = r#"
    class BadIdeas {
        #firstName;
        #firstName;
    }
    "#;
    let res = evaluate_script(script, None::<&std::path::Path>);
    assert!(res.is_err(), "Expected script to fail with a syntax error");
    let err = res.unwrap_err();
    let msg = err.message();
    assert!(msg.starts_with("SyntaxError"), "Expected a SyntaxError, got: {}", msg);
    assert!(
        msg.contains("#firstName"),
        "Expected message to mention '#firstName' but got: {}",
        msg
    );
    assert!(
        err.js_line().is_some() && err.js_column().is_some(),
        "Expected error to include js line and column"
    );
}

#[test]
fn delete_private_field_is_syntax_error() {
    let script = r#"
    class BadIdeas {
        #lastName;
        constructor() {
            delete this.#lastName;
        }
    }
    "#;
    let res = evaluate_script(script, None::<&std::path::Path>);
    assert!(res.is_err(), "Expected script to fail with a syntax error");
    let err = res.unwrap_err();
    let msg = err.message();
    assert!(msg.starts_with("SyntaxError"), "Expected a SyntaxError, got: {}", msg);
    assert!(
        err.js_line().is_some() && err.js_column().is_some(),
        "Expected delete error to include js line and column"
    );
}

#[test]
fn private_field_access_within_class_succeeds() {
    let script = r#"
    class Color {
        #values;
        constructor(r,g,b) { this.#values = [r,g,b]; }
        log() {
            console.log(this.#values);
        }
    }
    let tmp = new Color(1,2,3);
    tmp.log();
    "#;
    let res = evaluate_script(script, None::<&std::path::Path>);
    assert!(res.is_ok(), "Expected script to run without a syntax error");
}

#[test]
fn private_field_access_outside_class_reports_location() {
    let script = r#"
    class Color {
        #values;
    }
    // Accessing a private field outside the declaring class must be a SyntaxError
    console.log((new Color()).#values);
    "#;
    let res = evaluate_script(script, None::<&std::path::Path>);
    assert!(
        res.is_err(),
        "Expected script to fail with a syntax error when accessing private field outside class"
    );
    let err = res.unwrap_err();
    let msg = err.message();
    assert!(msg.starts_with("SyntaxError"), "Expected a SyntaxError, got: {}", msg);
    assert!(
        err.js_line().is_some() && err.js_column().is_some(),
        "Expected error to include js line and column"
    );
}

#[test]
fn eval_produces_throwable_syntax_error_instanceof() {
    let script = r#"
    try {
        eval("class BadIdeas { #firstName; #firstName; }");
        throw new Error('No error thrown');
    } catch (e) {
        if (!(e instanceof SyntaxError)) {
            throw new Error('Caught error is not a SyntaxError');
        }
    }
    "#;
    let res = evaluate_script(script, None::<&std::path::Path>);
    assert!(
        res.is_ok(),
        "Expected script to run and catch SyntaxError, got error: {:?}",
        res.err()
    );
}