boa_engine 0.17.0

Boa is a Javascript lexer, parser and compiler written in Rust. Currently, it has support for some of the language.
Documentation
use crate::{run_test_actions, JsNativeErrorKind, JsValue, TestAction};
use indoc::indoc;

#[test]
fn object_spread() {
    run_test_actions([
        TestAction::run(indoc! {r#"
                var b = {x: -1, z: -3}
                var a = {x: 1, y: 2, ...b};
            "#}),
        TestAction::assert_eq("a.x", -1),
        TestAction::assert_eq("a.y", 2),
        TestAction::assert_eq("a.z", -3),
    ]);
}

#[test]
fn spread_with_arguments() {
    run_test_actions([
        TestAction::run(indoc! {r#"
                const a = [1, "test", 3, 4];
                function foo(...a) {
                    return arguments;
                }

                var result = foo(...a);
            "#}),
        TestAction::assert_eq("result[0]", 1),
        TestAction::assert_eq("result[1]", "test"),
        TestAction::assert_eq("result[2]", 3),
        TestAction::assert_eq("result[3]", 4),
    ]);
}

#[test]
fn array_rest_with_arguments() {
    run_test_actions([
        TestAction::run_harness(),
        TestAction::run(indoc! {r#"
                var b = [4, 5, 6]
                var a = [1, 2, 3, ...b];
            "#}),
        TestAction::assert("arrayEquals(a, [ 1, 2, 3, 4, 5, 6 ])"),
    ]);
}

#[test]
fn spread_shallow_clone() {
    run_test_actions([TestAction::assert(indoc! {r#"
            var a = { x: {} };
            var aClone = { ...a };

            a.x === aClone.x
        "#})]);
}

#[test]
fn spread_merge() {
    run_test_actions([
        TestAction::run(indoc! {r#"
                var a = { x: 1, y: 2 };
                var b = { x: -1, z: -3, ...a };
            "#}),
        TestAction::assert_eq("b.x", 1),
        TestAction::assert_eq("b.y", 2),
        TestAction::assert_eq("b.z", -3),
    ]);
}

#[test]
fn spread_overriding_properties() {
    run_test_actions([
        TestAction::run(indoc! {r#"
                var a = { x: 0, y: 0 };
                var aWithOverrides = { ...a, ...{ x: 1, y: 2 } };
            "#}),
        TestAction::assert_eq("aWithOverrides.x", 1),
        TestAction::assert_eq("aWithOverrides.y", 2),
    ]);
}

#[test]
fn spread_getters_in_initializer() {
    run_test_actions([TestAction::assert_eq(
        indoc! {r#"
                var a = { x: 42 };
                var aWithXGetter = { ...a, get x() { throw new Error('not thrown yet') } };
            "#},
        JsValue::undefined(),
    )]);
}

#[test]
fn spread_getters_in_object() {
    run_test_actions([TestAction::assert_native_error(
        indoc! {r#"
            var a = { x: 42 };
            var aWithXGetter = { ...a, ... { get x() { throw new Error('not thrown yet') } } };
        "#},
        JsNativeErrorKind::Error,
        "not thrown yet",
    )]);
}

#[test]
fn spread_setters() {
    run_test_actions([TestAction::assert_eq(
        "var z = { set x(nexX) { throw new Error() }, ... { x: 1 } }",
        JsValue::undefined(),
    )]);
}

#[test]
fn spread_null_and_undefined_ignored() {
    run_test_actions([
        TestAction::run("var a = { ...null, ...undefined };"),
        TestAction::assert("!(undefined in a)"),
        TestAction::assert("!(null in a)"),
    ]);
}

#[test]
fn spread_with_new() {
    run_test_actions([TestAction::assert_eq(
        indoc! {r#"
            function F(m) {
                this.m = m;
            }
            function f(...args) {
                return new F(...args);
            }
            f('message').m;
        "#},
        "message",
    )]);
}

#[test]
fn spread_with_call() {
    run_test_actions([TestAction::assert_eq(
        indoc! {r#"
            function f(m) {
                return m;
            }
            function g(...args) {
                return f(...args);
            }
            g('message');
        "#},
        "message",
    )]);
}