#[ctor::ctor(unsafe)]
fn __init_test_logger() {
let _ = env_logger::Builder::from_env(env_logger::Env::default()).is_test(true).try_init();
}
#[cfg(test)]
mod builtin_functions_tests {
use javascript::{JSErrorKind, evaluate_script};
#[test]
fn test_array_methods_exist() {
let script = "let arr = Array(); typeof arr.every";
let result = evaluate_script(script, false, None::<&std::path::Path>).unwrap();
assert_eq!(result, "\"function\"");
}
#[test]
fn test_math_constants() {
let script = "Math.PI";
let result = evaluate_script(script, false, None::<&std::path::Path>).unwrap();
assert_eq!(result, "3.141592653589793");
let script = "Math.E";
let result = evaluate_script(script, false, None::<&std::path::Path>).unwrap();
assert_eq!(result, "2.718281828459045");
}
#[test]
fn test_math_floor() {
let script = "Math.floor(3.7)";
let result = evaluate_script(script, false, None::<&std::path::Path>).unwrap();
assert_eq!(result, "3");
}
#[test]
fn test_math_ceil() {
let script = "Math.ceil(3.1)";
let result = evaluate_script(script, false, None::<&std::path::Path>).unwrap();
assert_eq!(result, "4");
}
#[test]
fn test_math_sqrt() {
let script = "Math.sqrt(9)";
let result = evaluate_script(script, false, None::<&std::path::Path>).unwrap();
assert_eq!(result, "3");
}
#[test]
fn test_math_pow() {
let script = "Math.pow(2, 3)";
let result = evaluate_script(script, false, None::<&std::path::Path>).unwrap();
assert_eq!(result, "8");
}
#[test]
fn test_math_sin() {
let script = "Math.sin(0)";
let result = evaluate_script(script, false, None::<&std::path::Path>).unwrap();
assert_eq!(result, "0");
}
#[test]
fn test_math_random() {
let script = "Math.random()";
let result = evaluate_script(script, false, None::<&std::path::Path>).unwrap();
assert!(
(0.0..1.0).contains(&result.parse::<f64>().unwrap()),
"Expected Math.random() to be in [0, 1), got {result}",
);
}
#[test]
fn test_math_clz32() {
let script = "Math.clz32(0)";
let result = evaluate_script(script, false, None::<&std::path::Path>).unwrap();
assert_eq!(result, "32");
let script2 = "Math.clz32(1)";
let result2 = evaluate_script(script2, false, None::<&std::path::Path>).unwrap();
assert_eq!(result2, "31");
let script3 = "Math.clz32(268435456)";
let result3 = evaluate_script(script3, false, None::<&std::path::Path>).unwrap();
assert_eq!(result3, "3");
let script4 = "Math.clz32(NaN)";
let result4 = evaluate_script(script4, false, None::<&std::path::Path>).unwrap();
assert_eq!(result4, "32");
}
#[test]
fn test_math_imul() {
let script = "Math.imul(2, 3)";
let result = evaluate_script(script, false, None::<&std::path::Path>).unwrap();
assert_eq!(result.parse::<f64>().unwrap(), 6.0);
let script2 = "Math.imul(-2, 3)";
let result2 = evaluate_script(script2, false, None::<&std::path::Path>).unwrap();
assert_eq!(result2.parse::<f64>().unwrap(), -6.0);
let script3 = "Math.imul(2147483647, 2)";
let result3 = evaluate_script(script3, false, None::<&std::path::Path>).unwrap();
assert_eq!(result3.parse::<f64>().unwrap(), -2.0); }
#[test]
fn test_math_max() {
let script = "Math.max(1, 5, 3, 9, 2)";
let result = evaluate_script(script, false, None::<&std::path::Path>).unwrap();
assert_eq!(result.parse::<f64>().unwrap(), 9.0);
let script2 = "Math.max(10, 20)";
let result2 = evaluate_script(script2, false, None::<&std::path::Path>).unwrap();
assert_eq!(result2.parse::<f64>().unwrap(), 20.0);
let script3 = "Math.max(42)";
let result3 = evaluate_script(script3, false, None::<&std::path::Path>).unwrap();
assert_eq!(result3.parse::<f64>().unwrap(), 42.0);
let script4 = "Math.max()";
let result4 = evaluate_script(script4, false, None::<&std::path::Path>).unwrap();
let n4 = result4.parse::<f64>().unwrap();
assert!(n4.is_infinite() && n4.is_sign_negative());
let script5 = "Math.max(1, NaN, 3)";
let result5 = evaluate_script(script5, false, None::<&std::path::Path>).unwrap();
assert!(result5.parse::<f64>().unwrap().is_nan());
let script6 = "Math.max(-5, -1, -10)";
let result6 = evaluate_script(script6, false, None::<&std::path::Path>).unwrap();
assert_eq!(result6.parse::<f64>().unwrap(), -1.0);
}
#[test]
fn test_math_min() {
let script = "Math.min(1, 5, 3, 9, 2)";
let result = evaluate_script(script, false, None::<&std::path::Path>).unwrap();
assert_eq!(result.parse::<f64>().unwrap(), 1.0);
let script2 = "Math.min(10, 20)";
let result2 = evaluate_script(script2, false, None::<&std::path::Path>).unwrap();
assert_eq!(result2.parse::<f64>().unwrap(), 10.0);
let script3 = "Math.min(42)";
let result3 = evaluate_script(script3, false, None::<&std::path::Path>).unwrap();
assert_eq!(result3.parse::<f64>().unwrap(), 42.0);
let script4 = "Math.min()";
let result4 = evaluate_script(script4, false, None::<&std::path::Path>).unwrap();
let n4 = result4.parse::<f64>().unwrap();
assert!(n4.is_infinite() && n4.is_sign_positive());
let script5 = "Math.min(1, NaN, 3)";
let result5 = evaluate_script(script5, false, None::<&std::path::Path>).unwrap();
assert!(result5.parse::<f64>().unwrap().is_nan());
let script6 = "Math.min(-5, -1, -10)";
let result6 = evaluate_script(script6, false, None::<&std::path::Path>).unwrap();
assert_eq!(result6.parse::<f64>().unwrap(), -10.0);
}
#[test]
fn test_parse_int() {
let script = "parseInt('42')";
let result = evaluate_script(script, false, None::<&std::path::Path>).unwrap();
assert_eq!(result.parse::<f64>().unwrap(), 42.0);
let script = "parseInt('3.14')";
let result = evaluate_script(script, false, None::<&std::path::Path>).unwrap();
assert_eq!(result.parse::<f64>().unwrap(), 3.0);
}
#[test]
#[allow(clippy::approx_constant)]
fn test_parse_float() {
let script = "parseFloat('3.14')";
let result = evaluate_script(script, false, None::<&std::path::Path>).unwrap();
assert_eq!(result.parse::<f64>().unwrap(), 3.14_f64);
}
#[test]
fn test_is_nan() {
let script = "isNaN(NaN)";
let result = evaluate_script(script, false, None::<&std::path::Path>).unwrap();
assert_eq!(result, "true");
let script = "isNaN(42)";
let result = evaluate_script(script, false, None::<&std::path::Path>).unwrap();
assert_eq!(result, "false");
}
#[test]
fn test_is_nan_uses_tonumber_coercion() {
let script = r#"
let calls = 0;
let value = {
[Symbol.toPrimitive]() {
calls++;
return "NaN";
}
};
isNaN(value) && calls === 1
"#;
let result = evaluate_script(script, false, None::<&std::path::Path>).unwrap();
assert_eq!(result, "true");
}
#[test]
fn test_is_nan_throws_when_toprimitive_returns_object() {
let script = r#"
let value = {
[Symbol.toPrimitive]() {
return {};
}
};
isNaN(value)
"#;
let result = evaluate_script(script, false, None::<&std::path::Path>);
match result {
Err(err) => match err.kind() {
JSErrorKind::TypeError { message, .. } => {
assert!(message.contains("primitive"));
}
_ => panic!("Expected TypeError, got {:?}", err),
},
Ok(value) => panic!("Expected TypeError, got {:?}", value),
}
}
#[test]
fn test_is_finite() {
let script = "isFinite(42)";
let result = evaluate_script(script, false, None::<&std::path::Path>).unwrap();
assert_eq!(result, "true");
let script = "isFinite(Infinity)";
let result = evaluate_script(script, false, None::<&std::path::Path>).unwrap();
assert_eq!(result, "false");
let script = "isFinite.length";
let result = evaluate_script(script, false, None::<&std::path::Path>).unwrap();
assert_eq!(result, "1");
}
#[test]
fn test_is_finite_uses_tonumber_coercion() {
let script = r#"
let calls = 0;
let value = {
[Symbol.toPrimitive]() {
calls++;
return "42";
}
};
isFinite(value) && calls === 1
"#;
let result = evaluate_script(script, false, None::<&std::path::Path>).unwrap();
assert_eq!(result, "true");
}
#[test]
fn test_global_this_is_the_global_object() {
let script = r#"
var marker = {};
let desc = Object.getOwnPropertyDescriptor(this, "globalThis");
globalThis === this &&
globalThis.globalThis === globalThis &&
globalThis.marker === marker &&
desc.enumerable === false &&
desc.writable === true &&
desc.configurable === true
"#;
let result = evaluate_script(script, false, None::<&std::path::Path>).unwrap();
assert_eq!(result, "true");
}
#[test]
fn test_strict_assignment_to_readonly_global_throws() {
let script = r#"
let nanThrows = false;
let undefinedThrows = false;
try {
eval("'use strict'; NaN = 12;");
} catch (err) {
nanThrows = err instanceof TypeError;
}
try {
eval("'use strict'; undefined = 12;");
} catch (err) {
undefinedThrows = err instanceof TypeError;
}
nanThrows && undefinedThrows
"#;
let result = evaluate_script(script, false, None::<&std::path::Path>).unwrap();
assert_eq!(result, "true");
}
#[test]
fn test_json_stringify() {
let script = "JSON.stringify(42)";
let result = evaluate_script(script, false, None::<&std::path::Path>).unwrap();
let inner: String = serde_json::from_str(&result).unwrap();
assert_eq!(inner, "42");
}
#[test]
fn test_json_parse_stringify_roundtrip() {
let script = r#"let obj = JSON.parse('{"name":"John","age":30,"city":"New York"}'); JSON.stringify(obj)"#;
let result = evaluate_script(script, false, None::<&std::path::Path>).unwrap();
let inner: String = serde_json::from_str(&result).unwrap();
assert_eq!(inner, r#"{"name":"John","age":30,"city":"New York"}"#);
}
#[test]
fn test_json_parse_array() {
let script = r#"let arr = JSON.parse('[1, "hello", true, null]'); arr.length"#;
let result = evaluate_script(script, false, None::<&std::path::Path>).unwrap();
assert_eq!(result.parse::<f64>().unwrap(), 4.0);
let script2 = r#"let arr = JSON.parse('[1, "hello", true, null]'); arr[0]"#;
let result2 = evaluate_script(script2, false, None::<&std::path::Path>).unwrap();
assert_eq!(result2.parse::<f64>().unwrap(), 1.0);
let script3 = r#"let arr = JSON.parse('[1, "hello", true, null]'); arr[1]"#;
let result3 = evaluate_script(script3, false, None::<&std::path::Path>).unwrap();
assert_eq!(result3, "\"hello\"");
let script4 = r#"let arr = JSON.parse('[1, "hello", true, null]'); arr[2]"#;
let result4 = evaluate_script(script4, false, None::<&std::path::Path>).unwrap();
assert_eq!(result4, "true");
let script5 = r#"let arr = JSON.parse('[1, "hello", true, null]'); arr[3]"#;
let result5 = evaluate_script(script5, false, None::<&std::path::Path>).unwrap();
assert_eq!(result5, "null");
}
#[test]
fn test_json_parse_and_stringify_metadata() {
let script = r#"
JSON.parse.name === "parse" &&
JSON.parse.length === 2 &&
JSON.stringify.name === "stringify" &&
JSON.stringify.length === 3
"#;
let result = evaluate_script(script, false, None::<&std::path::Path>).unwrap();
assert_eq!(result, "true");
}
#[test]
fn test_json_stringify_space_formats_nested_values() {
let script = r#"
JSON.stringify({ a: { b: [1, 2] } }, null, " ")
"#;
let result = evaluate_script(script, false, None::<&std::path::Path>).unwrap();
let inner: String = serde_json::from_str(&result).unwrap();
assert_eq!(inner, "{\n \"a\": {\n \"b\": [\n 1,\n 2\n ]\n }\n}");
}
#[test]
fn test_json_stringify_uses_property_order_snapshot() {
let script = r#"
const obj = { p1: "p1", p2: "p2", p3: "p3" };
Object.defineProperty(obj, "add", {
enumerable: true,
get() {
obj.extra = "extra";
return "add";
}
});
obj.p4 = "p4";
obj[2] = "2";
obj[0] = "0";
obj[1] = "1";
delete obj.p1;
delete obj.p3;
obj.p1 = "p1";
JSON.stringify(obj)
"#;
let result = evaluate_script(script, false, None::<&std::path::Path>).unwrap();
let inner: String = serde_json::from_str(&result).unwrap();
assert_eq!(inner, r#"{"0":"0","1":"1","2":"2","p2":"p2","add":"add","p4":"p4","p1":"p1"}"#);
}
#[test]
fn test_json_parse_invalid_input_throws_syntax_error() {
let script = r#"
try {
JSON.parse("\u000b1234");
false
} catch (err) {
err instanceof SyntaxError
}
"#;
let result = evaluate_script(script, false, None::<&std::path::Path>).unwrap();
assert_eq!(result, "true");
}
#[test]
fn test_json_parse_reviver_visits_root_and_children() {
let script = r#"
const calls = [];
const result = JSON.parse('{"b":1,"a":{"c":2}}', function(key, value) {
calls.push(key);
return value;
});
result.a.c === 2 && calls[calls.length - 1] === ""
"#;
let result = evaluate_script(script, false, None::<&std::path::Path>).unwrap();
assert_eq!(result, "true");
}
#[test]
fn test_json_parse_treats_dunder_proto_as_data_property() {
let script = r#"
const value = JSON.parse('{"__proto__": [1, 2]}');
Object.getPrototypeOf(value) === Object.prototype
&& Array.isArray(value.__proto__)
&& value.__proto__.length === 2
"#;
let result = evaluate_script(script, false, None::<&std::path::Path>).unwrap();
assert_eq!(result, "true");
}
#[test]
fn test_json_parse_coerces_text_via_tostring() {
let script = r#"
JSON.parse({
toString() { return '"ok"'; },
valueOf() { return '"bad"'; }
}) === "ok"
"#;
let result = evaluate_script(script, false, None::<&std::path::Path>).unwrap();
assert_eq!(result, "true");
}
#[test]
fn test_json_parse_reviver_treats_proxy_wrapped_arrays_as_arrays() {
let script = r#"
let visitedOther = false;
const proxy = new Proxy([], {});
proxy.other = 0;
JSON.parse('[null, null]', function(name, value) {
if (name === 'other') visitedOther = true;
this[1] = proxy;
return value;
});
visitedOther === false
"#;
let result = evaluate_script(script, false, None::<&std::path::Path>).unwrap();
assert_eq!(result, "true");
}
#[test]
fn test_json_stringify_omits_top_level_undefined_and_object_functions() {
let script = r#"
JSON.stringify(undefined) === undefined
&& JSON.stringify({ key() {} }) === "{}"
&& JSON.stringify([undefined, function() {}]) === "[null,null]"
"#;
let result = evaluate_script(script, false, None::<&std::path::Path>).unwrap();
assert_eq!(result, "true");
}
#[test]
fn test_json_stringify_calls_bigint_tojson_before_throwing() {
let script = r#"
BigInt.prototype.toJSON = function () { return "ok"; };
JSON.stringify(1n) === '"ok"'
"#;
let result = evaluate_script(script, false, None::<&std::path::Path>).unwrap();
assert_eq!(result, "true");
}
#[test]
fn test_json_stringify_uses_cross_realm_bigint_wrapper_tojson() {
let script = r#"
let other = __createRealm__().global;
let wrapped = other.Object(other.BigInt(100));
let threw = false;
try {
JSON.stringify(wrapped);
} catch (e) {
threw = e.constructor === TypeError;
}
other.BigInt.prototype.toJSON = function () { return this.toString(); };
threw
&& Object.getPrototypeOf(wrapped) === other.BigInt.prototype
&& JSON.stringify(wrapped) === '"100"'
"#;
let result = evaluate_script(script, false, None::<&std::path::Path>).unwrap();
assert_eq!(result, "true");
}
#[test]
fn test_json_stringify_replacer_array_filters_and_orders_keys() {
let script = r#"
JSON.stringify({b: 1, a: 2, c: 3}, ['c', 'b', 'a']) === '{"c":3,"b":1,"a":2}'
&& JSON.stringify([1, {a: 2}], []) === '[1,{}]'
&& JSON.stringify({undefined: 1}, [undefined]) === '{}'
"#;
let result = evaluate_script(script, false, None::<&std::path::Path>).unwrap();
assert_eq!(result, "true");
}
#[test]
fn test_json_stringify_replacer_array_observes_proxy_and_abrupt_length() {
let script = r#"
let proxyOk = JSON.stringify({a: 1, b: 2}, new Proxy(['b'], {})) === '{"b":2}';
let abruptLength = false;
try {
JSON.stringify(null, new Proxy([], {
get(_target, key) {
if (key === 'length') throw new Error('boom');
}
}));
} catch (e) {
abruptLength = e.name === 'Error';
}
let revoked = Proxy.revocable([], {});
revoked.revoke();
let revokedErr = false;
try {
JSON.stringify({}, revoked.proxy);
} catch (e) {
revokedErr = e.name === 'TypeError';
}
proxyOk && abruptLength && revokedErr
"#;
let result = evaluate_script(script, false, None::<&std::path::Path>).unwrap();
assert_eq!(result, "true");
}
#[test]
fn test_function_prototype_tostring_returns_native_function_syntax() {
let script = r#"
const src = (function example() {}).toString();
src === "function example() {}" || src === "function example() { [ native code ] }"
"#;
let result = evaluate_script(script, false, None::<&std::path::Path>).unwrap();
assert_eq!(result, "true");
}
#[test]
fn test_function_prototype_tostring_throws_on_non_callable_receiver() {
let script = r#"
let threw = false;
try {
Function.prototype.toString.call({});
} catch (e) {
threw = e.name === "TypeError";
}
threw
"#;
let result = evaluate_script(script, false, None::<&std::path::Path>).unwrap();
assert_eq!(result, "true");
}
#[test]
fn test_builtin_function_string_coercion_uses_function_tostring() {
let script = r#"
("" + Object.prototype.hasOwnProperty) === "function () { [ native code ] }"
"#;
let result = evaluate_script(script, false, None::<&std::path::Path>).unwrap();
assert_eq!(result, "true");
}
#[test]
fn test_array_push() {
let script = "let arr = Array(); let arr2 = arr.push(1); let arr3 = arr.push(2); arr.length";
let result = evaluate_script(script, false, None::<&std::path::Path>).unwrap();
assert_eq!(result.parse::<f64>().unwrap(), 2.0);
}
#[test]
fn test_array_pop() {
let script = "let arr = Array(); let arr2 = arr.push(1); let arr3 = arr.push(2); arr.pop()";
let result = evaluate_script(script, false, None::<&std::path::Path>).unwrap();
assert_eq!(result.parse::<f64>().unwrap(), 2.0);
}
#[test]
fn test_array_join() {
let script = "let arr = Array(); let arr2 = arr.push('a'); let arr3 = arr.push('b'); arr.join('-')";
let result = evaluate_script(script, false, None::<&std::path::Path>).unwrap();
let inner: String = serde_json::from_str(&result).unwrap();
assert_eq!(inner, "a-b");
}
#[test]
fn test_object_keys() {
let script = "let obj = {a: 1, b: 2}; Object.keys(obj).length";
let result = evaluate_script(script, false, None::<&std::path::Path>).unwrap();
assert_eq!(result, "2");
}
#[test]
fn test_object_assign() {
let script = "let target = {a: 1}; let source = {b: 2, c: 3}; Object.assign(target, source); target.c";
let result = evaluate_script(script, false, None::<&std::path::Path>).unwrap();
assert_eq!(result, "3");
let script2 =
"let target = {a: 1}; let source1 = {b: 2}; let source2 = {c: 3}; Object.assign(target, source1, source2); target.b + target.c";
let result2 = evaluate_script(script2, false, None::<&std::path::Path>).unwrap();
assert_eq!(result2, "5");
let script3 = "let target = {a: 1}; let result = Object.assign(target, {b: 2}); result.a + result.b";
let result3 = evaluate_script(script3, false, None::<&std::path::Path>).unwrap();
assert_eq!(result3, "3");
}
#[test]
fn test_object_create() {
let script = "let obj = Object.create(null); obj.a = 1; obj.a";
let result = evaluate_script(script, false, None::<&std::path::Path>).unwrap();
assert_eq!(result, "1");
let script2 = "let proto = {inherited: 'yes'}; let obj = Object.create(proto); obj.own = 'mine'; obj.inherited + obj.own";
let result2 = evaluate_script(script2, false, None::<&std::path::Path>).unwrap();
assert_eq!(result2, "\"yesmine\"");
let script3 = "let obj = Object.create({}, {prop: {value: 42}}); obj.prop";
let result3 = evaluate_script(script3, false, None::<&std::path::Path>).unwrap();
assert_eq!(result3, "42");
}
#[test]
fn test_encode_uri_component() {
let script = "encodeURIComponent('hello world')";
let result = evaluate_script(script, false, None::<&std::path::Path>).unwrap();
assert_eq!(result, "\"hello%20world\"");
}
#[test]
fn test_decode_uri_component() {
let script = "decodeURIComponent('hello%20world')";
let result = evaluate_script(script, false, None::<&std::path::Path>).unwrap();
assert_eq!(result, "\"hello world\"");
}
#[test]
fn test_number_constructor() {
let script = "Number('42.5')";
let result = evaluate_script(script, false, None::<&std::path::Path>).unwrap();
assert_eq!(result, "42.5");
}
#[test]
fn test_boolean_constructor() {
let script = "Boolean(1)";
let result = evaluate_script(script, false, None::<&std::path::Path>).unwrap();
assert_eq!(result, "true");
}
#[test]
fn test_eval_function() {
let script = "eval('\"hello\"')";
let result = evaluate_script(script, false, None::<&std::path::Path>).unwrap();
assert_eq!(result, "\"hello\"");
}
#[test]
fn test_eval_expression() {
let script = "eval('1 + 2')";
let result = evaluate_script(script, false, None::<&std::path::Path>).unwrap();
assert_eq!(result, "3");
}
#[test]
fn test_eval_name_property() {
let script = r#"
let desc = Object.getOwnPropertyDescriptor(eval, "name");
desc.value === "eval" &&
desc.writable === false &&
desc.enumerable === false &&
desc.configurable === true
"#;
let result = evaluate_script(script, false, None::<&std::path::Path>).unwrap();
assert_eq!(result, "true");
}
#[test]
fn test_error_message_property_attributes() {
let script = r#"
let desc = Object.getOwnPropertyDescriptor(new Error("boom"), "message");
let empty = new Error();
desc.value === "boom" &&
desc.writable === true &&
desc.enumerable === false &&
desc.configurable === true &&
!empty.hasOwnProperty("message") &&
empty.message === Error.prototype.message
"#;
let result = evaluate_script(script, false, None::<&std::path::Path>).unwrap();
assert_eq!(result, "true");
}
#[test]
fn test_error_to_string_spec_cases() {
let script = r#"
let invalidReceiverThrows = false;
let symbolMessageThrows = false;
let toPrimitiveThrows = false;
try {
Error.prototype.toString.call(undefined);
} catch (err) {
invalidReceiverThrows = err instanceof TypeError;
}
try {
Error.prototype.toString.call({ message: Symbol() });
} catch (err) {
symbolMessageThrows = err instanceof TypeError;
}
try {
Error.prototype.toString.call({ message: { valueOf: undefined, toString: undefined } });
} catch (err) {
toPrimitiveThrows = err instanceof TypeError;
}
let errWithEmptyName = new Error("ErrorMessage");
errWithEmptyName.name = "";
let errWithoutMessage = new Error();
errWithoutMessage.name = "";
invalidReceiverThrows &&
symbolMessageThrows &&
toPrimitiveThrows &&
errWithEmptyName.toString() === "ErrorMessage" &&
errWithoutMessage.toString() === ""
"#;
let result = evaluate_script(script, false, None::<&std::path::Path>).unwrap();
assert_eq!(result, "true");
}
#[test]
fn test_encode_uri() {
let script = "encodeURI('hello world')";
let result = evaluate_script(script, false, None::<&std::path::Path>).unwrap();
let inner = serde_json::from_str::<String>(&result).unwrap_or(result.clone());
assert_eq!(inner, "hello%20world");
}
#[test]
fn test_decode_uri() {
let script = "decodeURI('hello%20world')";
let result = evaluate_script(script, false, None::<&std::path::Path>).unwrap();
let inner = serde_json::from_str::<String>(&result).unwrap_or(result.clone());
assert_eq!(inner, "hello world");
}
#[test]
fn test_array_for_each() {
let script = "let arr = Array(); let arr2 = arr.push(1); let arr3 = arr.push(2); arr.forEach(function(x) { return x; })";
let result = evaluate_script(script, false, None::<&std::path::Path>).unwrap();
assert_eq!(result, "undefined");
}
#[test]
fn test_array_map() {
let script = "let arr = Array(); let arr2 = arr.push(1); let arr3 = arr.push(2); let mapped = arr.map(function(x) { return x * 2; }); mapped.length";
let result = evaluate_script(script, false, None::<&std::path::Path>).unwrap();
assert_eq!(result.parse::<f64>().unwrap(), 2.0);
}
#[test]
fn test_array_filter() {
let script = "let arr = Array(); let arr2 = arr.push(1); let arr3 = arr.push(2); let filtered = arr.filter(function(x) { return x > 1; }); filtered.length";
let result = evaluate_script(script, false, None::<&std::path::Path>).unwrap();
assert_eq!(result.parse::<f64>().unwrap(), 1.0);
}
#[test]
fn test_array_reduce() {
let script = "let arr = Array(); let arr2 = arr.push(1); let arr3 = arr.push(2); let arr4 = arr.push(3); arr.reduce(function(acc, x) { return acc + x; }, 0)";
let result = evaluate_script(script, false, None::<&std::path::Path>).unwrap();
assert_eq!(result.parse::<f64>().unwrap(), 6.0);
}
#[test]
fn test_string_split_simple() {
let script = "let parts = 'a,b,c'.split(','); parts.length";
let result = evaluate_script(script, false, None::<&std::path::Path>).unwrap();
assert_eq!(result.parse::<f64>().unwrap(), 3.0);
}
#[test]
fn test_string_split_empty_sep() {
let script = "let parts = 'abc'.split(''); parts.length";
let result = evaluate_script(script, false, None::<&std::path::Path>).unwrap();
assert_eq!(result.parse::<f64>().unwrap(), 3.0);
}
#[test]
fn test_string_split_no_args() {
let script = "let parts = 'hello world'.split(); parts.length";
let result = evaluate_script(script, false, None::<&std::path::Path>).unwrap();
assert_eq!(result.parse::<f64>().unwrap(), 1.0);
let script = "let parts = 'hello world'.split(); parts[0]";
let result = evaluate_script(script, false, None::<&std::path::Path>).unwrap();
let inner = serde_json::from_str::<String>(&result).unwrap_or(result.clone());
assert_eq!(inner, "hello world");
}
#[test]
fn test_string_split_with_limit() {
let script = "let parts = 'a,b,c,d'.split(',', 2); parts.length";
let result = evaluate_script(script, false, None::<&std::path::Path>).unwrap();
assert_eq!(result.parse::<f64>().unwrap(), 2.0);
let script = "let parts = 'a,b,c,d'.split(',', 2); parts[0]";
let result = evaluate_script(script, false, None::<&std::path::Path>).unwrap();
let inner = serde_json::from_str::<String>(&result).unwrap_or(result.clone());
assert_eq!(inner, "a");
let script = "let parts = 'a,b,c,d'.split(',', 2); parts[1]";
let result = evaluate_script(script, false, None::<&std::path::Path>).unwrap();
let inner = serde_json::from_str::<String>(&result).unwrap_or(result.clone());
assert_eq!(inner, "b");
}
#[test]
fn test_string_char_at() {
let script = "'hello'.charAt(1)";
let result = evaluate_script(script, false, None::<&std::path::Path>).unwrap();
assert_eq!(result, "\"e\"");
}
#[test]
fn test_string_char_at_negative() {
let script = "'hello'.charAt(-1)";
let result = evaluate_script(script, false, None::<&std::path::Path>).unwrap();
let inner = serde_json::from_str::<String>(&result).unwrap_or(result.clone());
assert_eq!(inner.len(), 0);
}
#[test]
fn test_string_replace_functional() {
let script = "'hello world'.replace('world', 'there')";
let result = evaluate_script(script, false, None::<&std::path::Path>).unwrap();
let inner = serde_json::from_str::<String>(&result).unwrap_or(result.clone());
assert_eq!(inner, "hello there");
}
#[test]
fn test_string_substr() {
let script = "'hello world'.substr(2, 7)";
let result = evaluate_script(script, false, None::<&std::path::Path>).unwrap();
let inner = serde_json::from_str::<String>(&result).unwrap_or(result.clone());
assert_eq!(inner, "llo wor");
let script = "'hello world'.substr(-3)";
let result = evaluate_script(script, false, None::<&std::path::Path>).unwrap();
let inner = serde_json::from_str::<String>(&result).unwrap_or(result.clone());
assert_eq!(inner, "rld");
let script = "'my name is hello'.substr(3)";
let result = evaluate_script(script, false, None::<&std::path::Path>).unwrap();
let inner = serde_json::from_str::<String>(&result).unwrap_or(result.clone());
assert_eq!(inner, "name is hello");
let script = "'my name is hello'.substr(4, -7)";
let result = evaluate_script(script, false, None::<&std::path::Path>).unwrap();
let inner = serde_json::from_str::<String>(&result).unwrap_or(result.clone());
assert_eq!(inner, "");
let script = "'my name is hello'.substr(-7, 5)";
let result = evaluate_script(script, false, None::<&std::path::Path>).unwrap();
let inner = serde_json::from_str::<String>(&result).unwrap_or(result.clone());
assert_eq!(inner, "s hel");
}
#[test]
fn test_string_substring_swap() {
let script = "'hello world'.substring(5, 2)";
let result = evaluate_script(script, false, None::<&std::path::Path>).unwrap();
let inner = serde_json::from_str::<String>(&result).unwrap_or(result.clone());
assert_eq!(inner, "llo");
let script = "'hello world'.substring(-3)";
let result = evaluate_script(script, false, None::<&std::path::Path>).unwrap();
let inner = serde_json::from_str::<String>(&result).unwrap_or(result.clone());
assert_eq!(inner, "hello world");
let script = "'hello world'.substring(7, -2)";
let result = evaluate_script(script, false, None::<&std::path::Path>).unwrap();
let inner = serde_json::from_str::<String>(&result).unwrap_or(result.clone());
assert_eq!(inner, "hello w");
}
#[test]
fn test_array_map_values() {
let script = "let arr = Array(); let a2 = arr.push(1); let a3 = arr.push(2); let mapped = arr.map(function(x) { return x * 2; }); mapped.join(',')";
let result = evaluate_script(script, false, None::<&std::path::Path>).unwrap();
let inner = serde_json::from_str::<String>(&result).unwrap_or(result.clone());
assert_eq!(inner, "2,4");
}
#[test]
fn test_string_trim() {
let script = "' hello world '.trim()";
let result = evaluate_script(script, false, None::<&std::path::Path>).unwrap();
let inner = serde_json::from_str::<String>(&result).unwrap_or(result.clone());
assert_eq!(inner, "hello world");
}
#[test]
fn test_string_trim_end() {
let script = "' hello world '.trimEnd()";
let result = evaluate_script(script, false, None::<&std::path::Path>).unwrap();
let inner = serde_json::from_str::<String>(&result).unwrap_or(result.clone());
assert_eq!(inner, " hello world");
}
#[test]
fn test_string_trim_start() {
let script = "' hello world '.trimStart()";
let result = evaluate_script(script, false, None::<&std::path::Path>).unwrap();
let inner = serde_json::from_str::<String>(&result).unwrap_or(result.clone());
assert_eq!(inner, "hello world ");
}
#[test]
fn test_string_starts_with() {
let script = "'hello world'.startsWith('hello')";
let result = evaluate_script(script, false, None::<&std::path::Path>).unwrap();
assert_eq!(result, "true");
}
#[test]
fn test_string_ends_with() {
let script = "'hello world'.endsWith('world')";
let result = evaluate_script(script, false, None::<&std::path::Path>).unwrap();
assert_eq!(result, "true");
}
#[test]
fn test_string_includes() {
let script = "'hello world'.includes('lo wo')";
let result = evaluate_script(script, false, None::<&std::path::Path>).unwrap();
assert_eq!(result, "true");
}
#[test]
fn test_string_repeat() {
let script = "'ha'.repeat(3)";
let result = evaluate_script(script, false, None::<&std::path::Path>).unwrap();
let inner = serde_json::from_str::<String>(&result).unwrap_or(result.clone());
assert_eq!(inner, "hahaha");
}
#[test]
fn test_string_concat() {
let script = "'hello'.concat(' ', 'world', '!')";
let result = evaluate_script(script, false, None::<&std::path::Path>).unwrap();
let inner = serde_json::from_str::<String>(&result).unwrap_or(result.clone());
assert_eq!(inner, "hello world!");
}
#[test]
fn test_string_pad_start() {
let script = "'5'.padStart(3, '0')";
let result = evaluate_script(script, false, None::<&std::path::Path>).unwrap();
let inner = serde_json::from_str::<String>(&result).unwrap_or(result.clone());
assert_eq!(inner, "005");
}
#[test]
fn test_string_pad_end() {
let script = "'5'.padEnd(3, '0')";
let result = evaluate_script(script, false, None::<&std::path::Path>).unwrap();
let inner = serde_json::from_str::<String>(&result).unwrap_or(result.clone());
assert_eq!(inner, "500");
}
#[test]
fn test_string_index_of() {
let script = "'hello world'.indexOf('world')";
let result = evaluate_script(script, false, None::<&std::path::Path>).unwrap();
assert_eq!(result, "6");
let script = "'hello world'.indexOf('m')";
let result = evaluate_script(script, false, None::<&std::path::Path>).unwrap();
assert_eq!(result, "-1");
let script = "'hello world'.indexOf('l', 3)";
let result = evaluate_script(script, false, None::<&std::path::Path>).unwrap();
assert_eq!(result, "3");
let script = "'hello world'.indexOf('l', 4)";
let result = evaluate_script(script, false, None::<&std::path::Path>).unwrap();
assert_eq!(result, "9");
}
#[test]
fn test_string_last_index_of() {
let script = "'hello world'.lastIndexOf('l')";
let result = evaluate_script(script, false, None::<&std::path::Path>).unwrap();
assert_eq!(result, "9");
let script = "'hello world'.lastIndexOf('m')";
let result = evaluate_script(script, false, None::<&std::path::Path>).unwrap();
assert_eq!(result, "-1");
let script = "'hello world'.lastIndexOf('l', 8)";
let result = evaluate_script(script, false, None::<&std::path::Path>).unwrap();
assert_eq!(result, "3");
}
#[test]
fn test_array_find() {
let script = "let arr = Array(); let arr2 = arr.push(1); let arr3 = arr.push(2); let arr4 = arr.push(3); arr.find(function(x) { return x > 2; })";
let result = evaluate_script(script, false, None::<&std::path::Path>).unwrap();
assert_eq!(result, "3");
let script = "let arr = Array(); let arr2 = arr.push(1); let arr3 = arr.push(2); arr.find(function(x) { return x > 5; })";
let result = evaluate_script(script, false, None::<&std::path::Path>).unwrap();
assert_eq!(result, "undefined");
}
#[test]
fn test_array_find_index() {
let script = "let arr = Array(); let arr2 = arr.push(1); let arr3 = arr.push(2); let arr4 = arr.push(3); arr.findIndex(function(x) { return x > 2; })";
let result = evaluate_script(script, false, None::<&std::path::Path>).unwrap();
assert_eq!(result, "2");
let script = "let arr = Array(); let arr2 = arr.push(1); let arr3 = arr.push(2); arr.findIndex(function(x) { return x > 5; })";
let result = evaluate_script(script, false, None::<&std::path::Path>).unwrap();
assert_eq!(result, "-1");
}
#[test]
fn test_array_some() {
let script = "let arr = Array(); let arr2 = arr.push(1); let arr3 = arr.push(2); let arr4 = arr.push(3); arr.some(function(x) { return x > 2; })";
let result = evaluate_script(script, false, None::<&std::path::Path>).unwrap();
assert_eq!(result, "true");
let script = "let arr = Array(); let arr2 = arr.push(1); let arr3 = arr.push(2); arr.some(function(x) { return x > 5; })";
let result = evaluate_script(script, false, None::<&std::path::Path>).unwrap();
assert_eq!(result, "false");
}
#[test]
fn test_array_every() {
let script = "let arr = Array(); let arr2 = arr.push(2); let arr3 = arr.push(4); let arr4 = arr.push(6); arr.every(function(x) { return x > 1; })";
let result = evaluate_script(script, false, None::<&std::path::Path>).unwrap();
assert_eq!(result, "true");
let script = "let arr = Array(); let arr2 = arr.push(2); let arr3 = arr.push(1); let arr4 = arr.push(6); arr.every(function(x) { return x > 1; })";
let result = evaluate_script(script, false, None::<&std::path::Path>).unwrap();
assert_eq!(result, "false");
}
#[test]
fn test_array_concat() {
let script = "let arr1 = Array(); let arr2 = arr1.push(1); let arr3 = arr1.push(2); let arr4 = Array(); let arr5 = arr4.push(3); let arr6 = arr4.push(4); let result = arr1.concat(arr4); result.length";
let result = evaluate_script(script, false, None::<&std::path::Path>).unwrap();
assert_eq!(result.parse::<f64>().unwrap(), 4.0);
let script = "let arr1 = Array(); let arr2 = arr1.push(1); let result = arr1.concat(2, 3); result.length";
let result = evaluate_script(script, false, None::<&std::path::Path>).unwrap();
assert_eq!(result.parse::<f64>().unwrap(), 3.0);
}
#[test]
fn test_array_index_of() {
let script = "let arr = Array(); let arr2 = arr.push(1); let arr3 = arr.push(2); let arr4 = arr.push(3); arr.indexOf(2)";
let result = evaluate_script(script, false, None::<&std::path::Path>).unwrap();
assert_eq!(result.parse::<f64>().unwrap(), 1.0);
let script = "let arr = Array(); let arr2 = arr.push(1); let arr3 = arr.push(2); arr.indexOf(5)";
let result = evaluate_script(script, false, None::<&std::path::Path>).unwrap();
assert_eq!(result.parse::<f64>().unwrap(), -1.0);
let script = "let arr = Array(); let arr2 = arr.push(1); let arr3 = arr.push(2); let arr4 = arr.push(2); arr.indexOf(2, 2)";
let result = evaluate_script(script, false, None::<&std::path::Path>).unwrap();
assert_eq!(result.parse::<f64>().unwrap(), 2.0);
}
#[test]
fn test_array_includes() {
let script = "let arr = Array(); let arr2 = arr.push(1); let arr3 = arr.push(2); let arr4 = arr.push(3); arr.includes(2)";
let result = evaluate_script(script, false, None::<&std::path::Path>).unwrap();
assert_eq!(result, "true");
let script = "let arr = Array(); let arr2 = arr.push(1); let arr3 = arr.push(2); arr.includes(5)";
let result = evaluate_script(script, false, None::<&std::path::Path>).unwrap();
assert_eq!(result, "false");
let script = "let arr = Array(); let arr2 = arr.push(1); let arr3 = arr.push(2); let arr4 = arr.push(2); arr.includes(2, 2)";
let result = evaluate_script(script, false, None::<&std::path::Path>).unwrap();
assert_eq!(result, "true");
}
#[test]
fn test_array_sort() {
let script = "let arr = Array(); let arr2 = arr.push(3); let arr3 = arr.push(1); let arr4 = arr.push(2); let sorted = arr.sort(); sorted.join(',')";
let result = evaluate_script(script, false, None::<&std::path::Path>).unwrap();
let inner = serde_json::from_str::<String>(&result).unwrap_or(result.clone());
assert_eq!(inner, "1,2,3");
let script = "let arr = Array(); let arr2 = arr.push(3); let arr3 = arr.push(1); let arr4 = arr.push(2); let sorted = arr.sort(function(a, b) { return b - a; }); sorted.join(',')";
let result = evaluate_script(script, false, None::<&std::path::Path>).unwrap();
let inner = serde_json::from_str::<String>(&result).unwrap_or(result.clone());
assert_eq!(inner, "3,2,1");
}
#[test]
fn test_array_reverse() {
let script = "let arr = Array(); let arr2 = arr.push(1); let arr3 = arr.push(2); let arr4 = arr.push(3); let reversed = arr.reverse(); reversed.join(',')";
let result = evaluate_script(script, false, None::<&std::path::Path>).unwrap();
let inner = serde_json::from_str::<String>(&result).unwrap_or(result.clone());
assert_eq!(inner, "3,2,1");
}
#[test]
fn test_array_splice() {
let script =
"let arr = Array(); arr.push(1); arr.push(2); arr.push(3); arr.push(4); let removed = arr.splice(1, 2); removed.join(',')";
let result = evaluate_script(script, false, None::<&std::path::Path>).unwrap();
let inner = serde_json::from_str::<String>(&result).unwrap_or(result.clone());
assert_eq!(inner, "2,3");
let script2 = "let arr = Array(); arr.push(1); arr.push(4); let removed = arr.splice(1, 0, 2, 3); removed.length";
let result2 = evaluate_script(script2, false, None::<&std::path::Path>).unwrap();
assert_eq!(result2.parse::<f64>().unwrap(), 0.0); }
#[test]
fn test_array_shift() {
let script = "let arr = Array(); arr.push(1); arr.push(2); arr.push(3); let first = arr.shift(); arr.join(',')";
let result = evaluate_script(script, false, None::<&std::path::Path>).unwrap();
assert_eq!(result, "\"2,3\"");
let script2 = "let arr = Array(); arr.shift()";
let result2 = evaluate_script(script2, false, None::<&std::path::Path>).unwrap();
assert_eq!(result2, "undefined");
}
#[test]
fn test_array_unshift() {
let script = "let arr = Array(); arr.push(3); arr.push(4); let len = arr.unshift(1, 2); arr.join(',') + ',' + len";
let result = evaluate_script(script, false, None::<&std::path::Path>).unwrap();
assert_eq!(result, "\"1,2,3,4,4\"");
let script2 = "let arr = Array(); let len = arr.unshift(1, 2, 3); len";
let result2 = evaluate_script(script2, false, None::<&std::path::Path>).unwrap();
assert_eq!(result2, "3");
}
#[test]
fn test_array_fill() {
let script = "let arr = Array(); let arr2 = arr.push(1); let arr3 = arr.push(2); let arr4 = arr.push(3); let arr5 = arr.push(4); let filled = arr.fill(9, 1, 3); filled.join(',')";
let result = evaluate_script(script, false, None::<&std::path::Path>).unwrap();
assert_eq!(result, "\"1,9,9,4\"");
let script2 = "let arr = Array(); let arr2 = arr.push(1); let arr3 = arr.push(2); let arr4 = arr.push(3); let filled = arr.fill(0); filled.join(',')";
let result2 = evaluate_script(script2, false, None::<&std::path::Path>).unwrap();
assert_eq!(result2, "\"0,0,0\"");
}
#[test]
fn test_array_last_index_of() {
let script = "let arr = Array(); let arr2 = arr.push(1); let arr3 = arr.push(2); let arr4 = arr.push(3); let arr5 = arr.push(2); let arr6 = arr.push(1); arr.lastIndexOf(2)";
let result = evaluate_script(script, false, None::<&std::path::Path>).unwrap();
assert_eq!(result, "3");
let script2 = "let arr = Array(); let arr2 = arr.push(1); let arr3 = arr.push(2); let arr4 = arr.push(3); arr.lastIndexOf(4)";
let result2 = evaluate_script(script2, false, None::<&std::path::Path>).unwrap();
assert_eq!(result2, "-1");
let script3 = "let arr = Array(); let arr2 = arr.push(1); let arr3 = arr.push(2); let arr4 = arr.push(3); let arr5 = arr.push(2); arr.lastIndexOf(2, 2)";
let result3 = evaluate_script(script3, false, None::<&std::path::Path>).unwrap();
assert_eq!(result3, "1");
}
#[test]
fn test_array_to_string() {
let script = "let arr = Array(); let arr2 = arr.push(1); let arr3 = arr.push(2); let arr4 = arr.push(3); arr.toString()";
let result = evaluate_script(script, false, None::<&std::path::Path>).unwrap();
let inner = serde_json::from_str::<String>(&result).unwrap_or(result.clone());
assert_eq!(inner, "1,2,3");
let script2 = "let arr = Array(); arr.toString()";
let result2 = evaluate_script(script2, false, None::<&std::path::Path>).unwrap();
let inner2 = serde_json::from_str::<String>(&result2).unwrap_or(result2.clone());
assert_eq!(inner2, "");
let script3 = "let arr = Array(); arr.push(1); arr.push('hello'); arr.push(true); arr.toString()";
let result3 = evaluate_script(script3, false, None::<&std::path::Path>).unwrap();
let inner3 = serde_json::from_str::<String>(&result3).unwrap_or(result3.clone());
assert_eq!(inner3, "1,hello,true");
}
#[test]
fn test_array_flat() {
let script = "let arr = Array(); let subarr = Array(); subarr.push(2); subarr.push(3); arr.push(1); arr.push(subarr); arr.push(4); let flat = arr.flat(); flat.length === 4 && flat[0] === 1 && flat[1] === 2 && flat[2] === 3 && flat[3] === 4";
let result = evaluate_script(script, false, None::<&std::path::Path>).unwrap();
assert_eq!(result, "true");
}
#[test]
fn test_array_flat_map() {
let script = "let arr = Array(); arr.push(1); arr.push(2); let res = arr.flatMap(function(x) { let result = Array(); result.push(x); result.push(x*2); return result; }); res.length === 4 && res[0] === 1 && res[1] === 2 && res[2] === 2 && res[3] === 4";
let result = evaluate_script(script, false, None::<&std::path::Path>).unwrap();
assert_eq!(result, "true");
}
#[test]
fn test_array_copy_within() {
let script = "let arr = Array(); arr.push(1); arr.push(2); arr.push(3); arr.push(4); let res = arr.copyWithin(0, 2, 4); res.length === 4 && res[0] === 3 && res[1] === 4 && res[2] === 3 && res[3] === 4";
let result = evaluate_script(script, false, None::<&std::path::Path>).unwrap();
assert_eq!(result, "true");
}
#[test]
fn test_array_entries() {
let script = r#"
let arr = Array();
arr.push(1);
arr.push(2);
let entries = Array.from(arr.entries());
JSON.stringify(entries)
"#;
let result = evaluate_script(script, false, None::<&std::path::Path>).unwrap();
assert_eq!(result, "\"[[0,1],[1,2]]\"");
}
#[test]
fn test_array_from() {
let script = r#"
let arr = Array();
let arr2 = arr.push(1);
let arr3 = arr.push(2);
let res = Array.from(arr);
res.length === 2 && res[0] === 1 && res[1] === 2
"#;
let result = evaluate_script(script, false, None::<&std::path::Path>).unwrap();
assert_eq!(result, "true");
}
#[test]
fn test_array_is_array() {
let script = "let arr = Array(); arr.push(1); Array.isArray(arr)";
let result = evaluate_script(script, false, None::<&std::path::Path>).unwrap();
assert_eq!(result, "true");
let script2 = "Array.isArray(42)";
let result2 = evaluate_script(script2, false, None::<&std::path::Path>).unwrap();
assert_eq!(result2, "false");
}
#[test]
fn test_array_of() {
let script = "let res = Array.of(1, 2, 3); res.length === 3 && res[0] === 1 && res[1] === 2 && res[2] === 3";
let result = evaluate_script(script, false, None::<&std::path::Path>).unwrap();
assert_eq!(result, "true");
}
#[test]
fn test_typeof_operator() {
let script = "typeof 42";
let result = evaluate_script(script, false, None::<&std::path::Path>).unwrap();
let inner = serde_json::from_str::<String>(&result).unwrap_or(result.clone());
assert_eq!(inner, "number");
let script = "typeof 'hello'";
let result = evaluate_script(script, false, None::<&std::path::Path>).unwrap();
let inner = serde_json::from_str::<String>(&result).unwrap_or(result.clone());
assert_eq!(inner, "string");
let script = "typeof true";
let result = evaluate_script(script, false, None::<&std::path::Path>).unwrap();
let inner = serde_json::from_str::<String>(&result).unwrap_or(result.clone());
assert_eq!(inner, "boolean");
let script = "typeof undefined";
let result = evaluate_script(script, false, None::<&std::path::Path>).unwrap();
let inner = serde_json::from_str::<String>(&result).unwrap_or(result.clone());
assert_eq!(inner, "undefined");
let script = "typeof {}";
let result = evaluate_script(script, false, None::<&std::path::Path>).unwrap();
let inner = serde_json::from_str::<String>(&result).unwrap_or(result.clone());
assert_eq!(inner, "object");
let script = "typeof function(){}";
let result = evaluate_script(script, false, None::<&std::path::Path>).unwrap();
let inner = serde_json::from_str::<String>(&result).unwrap_or(result.clone());
assert_eq!(inner, "function");
}
#[test]
fn test_delete_operator() {
let script = "let obj = {}; obj.x = 42; delete obj.x; obj.x";
let result = evaluate_script(script, false, None::<&std::path::Path>).unwrap();
assert_eq!(result, "undefined");
let script = "let obj = {}; delete obj.nonexistent";
let result = evaluate_script(script, false, None::<&std::path::Path>).unwrap();
assert_eq!(result, "true");
let script = "let x = 42; delete x";
let result = evaluate_script(script, false, None::<&std::path::Path>);
assert!(result.is_err());
}
#[test]
fn test_void_operator() {
let script = "void 42";
let result = evaluate_script(script, false, None::<&std::path::Path>).unwrap();
assert_eq!(result, "undefined");
let script = "void (1 + 2 + 3)";
let result = evaluate_script(script, false, None::<&std::path::Path>).unwrap();
assert_eq!(result, "undefined");
let script = "void 'hello'";
let result = evaluate_script(script, false, None::<&std::path::Path>).unwrap();
assert_eq!(result, "undefined");
}
#[test]
fn test_in_operator() {
let script = "let obj = {}; obj.x = 42; 'x' in obj";
let result = evaluate_script(script, false, None::<&std::path::Path>).unwrap();
assert_eq!(result, "true");
let script = "let obj = {}; 'nonexistent' in obj";
let result = evaluate_script(script, false, None::<&std::path::Path>).unwrap();
assert_eq!(result, "false");
let script = "let proto = {}; proto.inherited = 'yes'; let xyz = {}; xyz.__proto__ = proto; 'inherited' in xyz";
let result = evaluate_script(script, false, None::<&std::path::Path>).unwrap();
assert_eq!(result, "true");
}
#[test]
fn test_array_find_last() {
let script = "let arr = [1, 2, 3, 4, 5]; arr.findLast(x => x % 2 === 0)";
let result = evaluate_script(script, false, None::<&std::path::Path>).unwrap();
assert_eq!(result.parse::<f64>().unwrap(), 4.0);
let script2 = "let arr = [1, 3, 5]; arr.findLast(x => x % 2 === 0)";
let result2 = evaluate_script(script2, false, None::<&std::path::Path>).unwrap();
assert_eq!(result2, "undefined");
let script3 = "let arr = ['a', 'b', 'c']; arr.findLast(x => x === 'b')";
let result3 = evaluate_script(script3, false, None::<&std::path::Path>).unwrap();
let inner = serde_json::from_str::<String>(&result3).unwrap_or(result3.clone());
assert_eq!(inner, "b");
}
#[test]
fn test_array_find_last_index() {
let script = "let arr = [1, 2, 3, 4, 5]; arr.findLastIndex(x => x % 2 === 0)";
let result = evaluate_script(script, false, None::<&std::path::Path>).unwrap();
assert_eq!(result.parse::<f64>().unwrap(), 3.0);
let script2 = "let arr = [1, 3, 5]; arr.findLastIndex(x => x % 2 === 0)";
let result2 = evaluate_script(script2, false, None::<&std::path::Path>).unwrap();
assert_eq!(result2.parse::<f64>().unwrap(), -1.0);
let script3 = "let arr = ['a', 'b', 'c', 'b']; arr.findLastIndex(x => x === 'b')";
let result3 = evaluate_script(script3, false, None::<&std::path::Path>).unwrap();
assert_eq!(result3.parse::<f64>().unwrap(), 3.0);
}
}