use javascript::{Value, evaluate_script};
#[test]
fn stage1_map_comprehensive() {
let result = evaluate_script(
r#"
let map = new Map();
map.set('key1', 'value1');
map.set('key2', 42);
map.set({}, 'object_key');
map.size
"#,
None::<&std::path::Path>,
)
.unwrap();
match result {
Value::Number(n) => assert_eq!(n, 3.0),
_ => panic!("Expected number 3, got {:?}", result),
}
let result = evaluate_script(
r#"
let map = new Map([['a', 1], ['b', 2]]);
let sum = 0;
for (let [key, value] of map) {
sum += value;
}
sum
"#,
None::<&std::path::Path>,
)
.unwrap();
match result {
Value::Number(n) => assert_eq!(n, 3.0),
_ => panic!("Expected number 3, got {:?}", result),
}
let result = evaluate_script(
r#"
let map = new Map([['x', 10], ['y', 20]]);
map.has('x') && map.get('x') === 10 && map.delete('x') && !map.has('x') && map.size === 1
"#,
None::<&std::path::Path>,
)
.unwrap();
match result {
Value::Boolean(b) => assert!(b),
_ => panic!("Expected true, got {:?}", result),
}
}
#[test]
fn stage1_set_comprehensive() {
let result = evaluate_script(
r#"
let set = new Set([1, 2, 3, 2, 1]);
set.size
"#,
None::<&std::path::Path>,
)
.unwrap();
match result {
Value::Number(n) => assert_eq!(n, 3.0),
_ => panic!("Expected number 3, got {:?}", result),
}
let result = evaluate_script(
r#"
let set = new Set([1, 2, 3]);
let sum = 0;
for (let value of set) {
sum += value;
}
sum
"#,
None::<&std::path::Path>,
)
.unwrap();
match result {
Value::Number(n) => assert_eq!(n, 6.0),
_ => panic!("Expected number 6, got {:?}", result),
}
let result = evaluate_script(
r#"
let set = new Set([1, 2, 3]);
set.has(2) && set.delete(2) && !set.has(2) && set.size === 2
"#,
None::<&std::path::Path>,
)
.unwrap();
match result {
Value::Boolean(b) => assert!(b),
_ => panic!("Expected true, got {:?}", result),
}
}
#[test]
fn stage1_weakmap_weakset() {
let result = evaluate_script(
r#"
let wm = new WeakMap();
let key = {};
wm.set(key, 'value');
wm.has(key) && wm.get(key) === 'value'
"#,
None::<&std::path::Path>,
)
.unwrap();
match result {
Value::Boolean(b) => assert!(b),
_ => panic!("Expected true, got {:?}", result),
}
let result = evaluate_script(
r#"
let ws = new WeakSet();
let obj = {};
ws.add(obj);
ws.has(obj)
"#,
None::<&std::path::Path>,
)
.unwrap();
match result {
Value::Boolean(b) => assert!(b),
_ => panic!("Expected true, got {:?}", result),
}
}
#[test]
fn stage1_generator_functions() {
let result = evaluate_script(
r#"
function* gen() {
yield 42;
}
var g = gen();
var result = g.next();
result.value;
"#,
None::<&std::path::Path>,
);
assert!(result.is_ok());
match result.unwrap() {
Value::Number(n) => assert_eq!(n, 42.0),
_ => panic!("Expected number 42.0"),
}
let result = evaluate_script(
r#"
function* gen() {
yield 42;
}
var g = gen();
g.next(); // first call
var result = g.next(); // second call should be done
result.done;
"#,
None::<&std::path::Path>,
);
assert!(result.is_ok());
match result.unwrap() {
Value::Boolean(b) => assert!(b),
_ => panic!("Expected boolean true"),
}
let result = evaluate_script(
r#"
function* gen() {
yield 1;
}
typeof gen;
"#,
None::<&std::path::Path>,
)
.unwrap();
match result {
Value::String(s) => assert_eq!(String::from_utf16_lossy(&s), "function"),
_ => panic!("Expected string 'function', got {:?}", result),
}
let result = evaluate_script(
r#"
function* gen() {
yield 1;
}
var g = gen();
typeof g;
"#,
None::<&std::path::Path>,
)
.unwrap();
match result {
Value::String(s) => assert_eq!(String::from_utf16_lossy(&s), "object"),
_ => panic!("Expected string 'object', got {:?}", result),
}
}
#[test]
fn stage1_iterator_protocol() {
let result = evaluate_script(
r#"
let arr = [10, 20, 30];
let sum = 0;
for (let num of arr) {
sum += num;
}
sum
"#,
None::<&std::path::Path>,
)
.unwrap();
match result {
Value::Number(n) => assert_eq!(n, 60.0),
_ => panic!("Expected number 60, got {:?}", result),
}
let result = evaluate_script(
r#"
let map = new Map([['a', 1], ['b', 2], ['c', 3]]);
let sum = 0;
for (let [key, value] of map) {
sum += value;
}
sum
"#,
None::<&std::path::Path>,
)
.unwrap();
match result {
Value::Number(n) => assert_eq!(n, 6.0),
_ => panic!("Expected number 6, got {:?}", result),
}
let result = evaluate_script(
r#"
let set = new Set([1, 2, 3, 2, 1]);
let sum = 0;
for (let value of set) {
sum += value;
}
sum
"#,
None::<&std::path::Path>,
)
.unwrap();
match result {
Value::Number(n) => assert_eq!(n, 6.0),
_ => panic!("Expected number 6, got {:?}", result),
}
let result = evaluate_script(
r#"
let customIterable = {
iterator: function() {
let count = 0;
return {
next: function() {
count++;
if (count <= 3) {
return { value: count * 10, done: false };
} else {
return { value: undefined, done: true };
}
}
};
}
};
let sum = 0;
let iter = customIterable.iterator();
let result;
while (!(result = iter.next()).done) {
sum += result.value;
}
sum
"#,
None::<&std::path::Path>,
)
.unwrap();
match result {
Value::Number(n) => assert_eq!(n, 60.0),
_ => panic!("Expected number 60, got {:?}", result),
}
}
#[test]
fn stage1_proxy_basic() {
let result = evaluate_script(
r#"
let target = { foo: 42 };
let handler = {
get: function(target, prop) {
if (prop === 'foo') {
return target[prop] * 2;
}
return target[prop];
}
};
let proxy = new Proxy(target, handler);
proxy.foo
"#,
None::<&std::path::Path>,
)
.unwrap();
match result {
Value::Number(n) => assert_eq!(n, 84.0),
_ => panic!("Expected number 84, got {:?}", result),
}
let result = evaluate_script(
r#"
let target = {};
let handler = {
set: function(target, prop, value) {
target[prop] = value * 2;
return true;
}
};
let proxy = new Proxy(target, handler);
proxy.x = 5;
proxy.x
"#,
None::<&std::path::Path>,
)
.unwrap();
match result {
Value::Number(n) => assert_eq!(n, 10.0),
_ => panic!("Expected number 10, got {:?}", result),
}
}
#[test]
fn stage1_proxy_revocable() {
let result = evaluate_script(
r#"
let target = { foo: 42 };
let handler = {
get: function(target, prop) {
return target[prop];
}
};
let revocable = Proxy.revocable(target, handler);
let proxy = revocable.proxy;
let result1 = proxy.foo;
revocable.revoke();
let result2 = 'revoked';
result1
"#,
None::<&std::path::Path>,
)
.unwrap();
match result {
Value::Number(n) => assert_eq!(n, 42.0),
_ => panic!("Expected number 42, got {:?}", result),
}
}
#[test]
fn stage1_proxy_delete_trap() {
let result = evaluate_script(
r#"
let target = { foo: 42, bar: 24 };
let handler = {
deleteProperty: function(target, prop) {
if (prop === 'foo') {
return false; // Prevent deletion
}
return delete target[prop];
}
};
let proxy = new Proxy(target, handler);
delete proxy.bar; // Should work
let deleted_bar = !('bar' in proxy);
delete proxy.foo; // Should be prevented
let still_has_foo = 'foo' in proxy;
deleted_bar && still_has_foo
"#,
None::<&std::path::Path>,
)
.unwrap();
match result {
Value::Boolean(b) => assert!(b),
_ => panic!("Expected true, got {:?}", result),
}
}
#[test]
fn stage1_integration_all_features() {
let result = evaluate_script(
r#"
// Test Map operations
let map = new Map();
map.set('a', 1);
map.set('b', 2);
let mapSize = map.size;
// Test Set operations
let set = new Set([1, 2, 3]);
let setSum = 0;
for (let val of set) {
setSum += val;
}
// Test generator function (basic functionality - implementation incomplete)
function* simpleGen() {
yield 10;
yield 20;
}
let gen = simpleGen();
let genType = typeof gen; // Should be 'object'
let canCallNext = typeof gen.next === 'function'; // Should be true
// Test Proxy
let target = { value: 42 };
let proxy = new Proxy(target, {
get: function(target, prop) {
if (prop === 'value') {
return target[prop] * 2;
}
return target[prop];
}
});
let proxyValue = proxy.value;
console.log(mapSize, setSum, genType, canCallNext, proxyValue);
// Combine results
mapSize === 2 && setSum === 6 && genType === 'object' && canCallNext && proxyValue === 84
"#,
None::<&std::path::Path>,
)
.unwrap();
match result {
Value::Boolean(b) => assert!(b),
_ => panic!("Expected true, got {:?}", result),
}
}
#[test]
fn stage1_error_handling() {
let result = evaluate_script(
r#"
let proxy = new Proxy({}, {});
proxy.foo === undefined
"#,
None::<&std::path::Path>,
)
.unwrap();
match result {
Value::Boolean(b) => assert!(b),
_ => panic!("Expected true, got {:?}", result),
}
let result = evaluate_script(
r#"
let revocable = Proxy.revocable({foo: 42}, {});
let proxy = revocable.proxy;
let value = proxy.foo; // Get value before revoke
revocable.revoke();
value === 42
"#,
None::<&std::path::Path>,
)
.unwrap();
match result {
Value::Boolean(b) => assert!(b),
_ => panic!("Expected true, got {:?}", result),
}
let result = evaluate_script(
r#"
try {
throw 42;
} catch (e) {
e === 42
}
"#,
None::<&std::path::Path>,
)
.unwrap();
match result {
Value::Boolean(b) => assert!(b),
_ => panic!("Expected true, got {:?}", result),
}
}