use std::sync::Arc; use oxide_compiler::compiler::Compiler; use oxide_types::value::JsValue; use oxide_vm::vm::Vm; fn eval(vm: &mut Vm, source: &str) -> Result { let allocator = oxide_parser::Allocator::default(); let program = oxide_parser::parse(&allocator, source).map_err(|e| format!("Parse error: {:?}", e))?; let module = Compiler::new().compile(&program).map_err(|e| format!("Compile error: {}", e))?; vm.run(&Arc::new(module)) } fn to_str(vm: &Vm, val: JsValue) -> String { vm.lookup_str(val).unwrap_or_default() } #[test] fn reflect_global_and_methods_exist() { let mut vm = Vm::new(); let result = eval( &mut vm, "typeof Reflect === 'object' && typeof Reflect.get === 'function' && typeof Reflect.construct === 'function'", ) .unwrap(); assert!(result.as_bool()); } #[test] fn reflect_get_set_has_delete_property() { let mut vm = Vm::new(); let result = eval( &mut vm, "var obj = {a: 1, b: 2}; \ var getOk = Reflect.get(obj, 'a') === 1; \ var setOk = Reflect.set(obj, 'c', 3) === true && obj.c === 3; \ var hasOk = Reflect.has(obj, 'a') === true && Reflect.has(obj, 'z') === false; \ var delOk = Reflect.deleteProperty(obj, 'a') === true && Reflect.has(obj, 'a') === false; \ getOk && setOk && hasOk && delOk", ) .unwrap(); assert!(result.as_bool()); } #[test] fn reflect_own_keys_returns_own_property_names() { let mut vm = Vm::new(); let result = eval( &mut vm, "var obj = {a: 1, b: 2}; Reflect.set(obj, 'c', 3); Reflect.ownKeys(obj).join(',')", ) .unwrap(); assert_eq!(to_str(&vm, result), "a,b,c"); } #[test] fn reflect_get_own_property_descriptor_returns_descriptor() { let mut vm = Vm::new(); let result = eval( &mut vm, "var obj = {}; Reflect.defineProperty(obj, 'x', { value: 9, writable: true, enumerable: true, configurable: true }); \ var d = Reflect.getOwnPropertyDescriptor(obj, 'x'); d.value === 9 && d.writable === true", ) .unwrap(); assert!(result.as_bool()); } #[test] fn reflect_prototype_and_extensible_methods() { let mut vm = Vm::new(); let result = eval( &mut vm, "var proto = {p: 1}; var obj = {}; \ var setProto = Reflect.setPrototypeOf(obj, proto); \ var getProto = Reflect.getPrototypeOf(obj) === proto; \ var ext1 = Reflect.isExtensible(obj); \ var prevent = Reflect.preventExtensions(obj); \ var ext2 = Reflect.isExtensible(obj); \ setProto && getProto && ext1 === true && prevent === true && ext2 === false", ) .unwrap(); assert!(result.as_bool()); } // 不可扩展目标:新旧不同返回 false,新旧相同返回 true,且原值不被改写。 #[test] fn reflect_set_prototype_of_non_extensible_returns_false() { let mut vm = Vm::new(); let result = eval( &mut vm, "var a = {}; Object.preventExtensions(a); \ var diff = Reflect.setPrototypeOf(a, null); \ var kept = Object.getPrototypeOf(a) === Object.prototype; \ var same = Reflect.setPrototypeOf(a, Object.prototype); \ diff === false && kept && same === true", ) .unwrap(); assert!(result.as_bool()); } #[test] fn reflect_apply_calls_function() { let mut vm = Vm::new(); let result = eval( &mut vm, "function add(a, b) { return this.base + a + b; } var receiver = {base: 10}; var args = [1, 2]; Reflect.apply(add, receiver, args)", ) .unwrap(); assert_eq!(result.as_int(), 13, "this.base 10 + 1 + 2 = 13"); } #[test] fn reflect_construct_returns_new_instance() { let mut vm = Vm::new(); let result = eval( &mut vm, "var o = Reflect.construct(function(){ this.x = 5; }, []); typeof o === 'object' && o.x === 5", ) .unwrap(); assert!(result.as_bool()); } #[test] fn reflect_construct_non_callable_target_throws_type_error() { let mut vm = Vm::new(); let result = eval(&mut vm, "try { Reflect.construct(123, []) } catch (e) { e instanceof TypeError }").unwrap(); assert!(result.as_bool()); } #[test] fn reflect_non_object_target_throws_type_error() { let mut vm = Vm::new(); let result = eval(&mut vm, "try { Reflect.get(1, 'x') } catch (e) { e instanceof TypeError }").unwrap(); assert!(result.as_bool()); } // 派生类(extends Array)经 Reflect.construct 产出真实例:isArray 与 length 就位。 #[test] fn reflect_construct_derived_class_instance() { let mut vm = Vm::new(); let result = eval( &mut vm, "class B extends Array { constructor(x) { super(x); } } \ var inst = Reflect.construct(B, [2]); \ inst instanceof B && Array.isArray(inst) && inst.length === 2", ) .unwrap(); assert!(result.as_bool()); } // 派生类经 Reflect.construct 正常走 super 链构造,实例值判别。 #[test] fn reflect_construct_derived_extends_base_class() { let mut vm = Vm::new(); let result = eval( &mut vm, "class Base { constructor(x) { this.x = x; } } \ class D extends Base { constructor(x) { super(x); } } \ var inst = Reflect.construct(D, [9]); \ inst instanceof D && inst.x === 9", ) .unwrap(); assert!(result.as_bool()); } // 无 newTarget 时构造帧内 new.target = target。 #[test] fn reflect_construct_new_target_defaults_to_target() { let mut vm = Vm::new(); let result = eval( &mut vm, "var newTarget = null; function f() { newTarget = new.target; } \ Reflect.construct(f, []); newTarget === f", ) .unwrap(); assert!(result.as_bool()); } // newTarget 覆写臂:构造帧内 new.target = newTarget,实例 proto 取 newTarget.prototype。 #[test] fn reflect_construct_new_target_override() { let mut vm = Vm::new(); let result = eval( &mut vm, "var newTarget = null; function f() { newTarget = new.target; } \ var NT = function() {}; \ Reflect.construct(f, [], NT); \ newTarget === NT && Object.getPrototypeOf(Reflect.construct(f, [], NT)) === NT.prototype", ) .unwrap(); assert!(result.as_bool()); } // 派生类 + newTarget 覆写全形:super 实参逐位、new.target = NT、this = 实例。 #[test] fn reflect_construct_derived_with_new_target() { let mut vm = Vm::new(); let result = eval( &mut vm, "var expectedNewTarget = function() {}; \ var thisValue, instance, args, actualNewTarget; \ function Parent() { thisValue = this; args = arguments; actualNewTarget = new.target; } \ class Child extends Parent { constructor() { super(1, 2, 3); } } \ instance = Reflect.construct(Child, [4, 5, 6], expectedNewTarget); \ thisValue === instance && args.length === 3 && args[0] === 1 && args[1] === 2 && args[2] === 3 \ && actualNewTarget === expectedNewTarget \ && Object.getPrototypeOf(instance) === expectedNewTarget.prototype", ) .unwrap(); assert!(result.as_bool()); } // 基类 + newTarget 覆写:实例 proto 取 NT.prototype,new.target = NT。 #[test] fn reflect_construct_base_class_with_new_target() { let mut vm = Vm::new(); let result = eval( &mut vm, "class CBase { constructor(x) { this.x = x; this.nt = new.target; } } \ var NT = function() {}; \ var inst = Reflect.construct(CBase, [5], NT); \ Object.getPrototypeOf(inst) === NT.prototype && inst.nt === NT && inst.x === 5", ) .unwrap(); assert!(result.as_bool()); } // 入参面:target 非构造器(Date.now / 箭头 / 基元)均 TypeError。 #[test] fn reflect_construct_non_constructor_target_throws() { let mut vm = Vm::new(); let result = eval( &mut vm, "var t1 = false, t2 = false, t3 = false; \ try { Reflect.construct(Date.now, [], Array); } catch (e) { t1 = e instanceof TypeError; } \ try { Reflect.construct((a) => a, []); } catch (e) { t2 = e instanceof TypeError; } \ try { Reflect.construct(1, []); } catch (e) { t3 = e instanceof TypeError; } \ t1 && t2 && t3", ) .unwrap(); assert!(result.as_bool()); } // 入参面:newTarget 非构造器与 argumentsList 非对象均 TypeError。 #[test] fn reflect_construct_invalid_new_target_or_arguments_list_throws() { let mut vm = Vm::new(); let result = eval( &mut vm, "var t1 = false, t2 = false; \ try { Reflect.construct(function(){}, [], 1); } catch (e) { t1 = e instanceof TypeError; } \ try { Reflect.construct(function(){}, 1); } catch (e) { t2 = e instanceof TypeError; } \ t1 && t2", ) .unwrap(); assert!(result.as_bool()); } // length 访问器抛出的异常原值传播(不降级、不吞没)。 #[test] fn reflect_construct_length_getter_exception_propagates() { let mut vm = Vm::new(); let result = eval( &mut vm, "var o = {}; \ Object.defineProperty(o, 'length', { get: function() { throw new RangeError('len'); } }); \ try { Reflect.construct(function(a){ return a; }, o); false } catch (e) { e instanceof RangeError }", ) .unwrap(); assert!(result.as_bool()); } // array-like 对象按规范 Get 逐位取值(非位序直读),值与实参个数就位。 #[test] fn reflect_construct_array_like_elements_read_by_get() { let mut vm = Vm::new(); let result = eval( &mut vm, "var captured; \ function C(a, b) { captured = [typeof a, arguments.length]; } \ Reflect.construct(C, { length: 2, 0: 'a', 1: 'b' }); \ captured[0] === 'string' && captured[1] === 2", ) .unwrap(); assert!(result.as_bool()); } // 守卫面:native 构造器(Array 填槽)、构造帧 arguments 完整、显式返回对象 // 优先、绑定元数据(isConstructor(Reflect.construct) === false)。 #[test] fn reflect_construct_guard_face() { let mut vm = Vm::new(); let result = eval( &mut vm, "var arr = Reflect.construct(Array, [3]); \ function fn() { this.args = arguments; } \ var result = Reflect.construct(fn, [42, 'Mike', 'Leo']); \ var retObj = Reflect.construct(function() { return { z: 9 }; }, []); \ var meta = false; \ try { Reflect.construct(Reflect.construct, []); } catch (e) { meta = e instanceof TypeError; } \ arr instanceof Array && arr.length === 3 \ && result.args.length === 3 && result.args[0] === 42 && result.args[1] === 'Mike' && result.args[2] === 'Leo' \ && retObj.z === 9 && !(retObj instanceof Function) && meta", ) .unwrap(); assert!(result.as_bool()); } // 键转换异常原值传播:Reflect.has 的键 ToPropertyKey 抛 "X" → 捕获值 === "X"。 #[test] fn reflect_has_propagates_key_conversion_original_value() { let mut vm = Vm::new(); let result = eval( &mut vm, "var key = { toString: function() { throw 'X'; } }; \ var caught; \ try { Reflect.has({}, key); caught = 'none'; } catch (e) { caught = e; } \ caught === 'X'", ) .unwrap(); assert!(result.as_bool()); } // 同族探针:Reflect.get 的键转换异常同式原值传播。 #[test] fn reflect_get_propagates_key_conversion_original_value() { let mut vm = Vm::new(); let result = eval( &mut vm, "var key = { toString: function() { throw 'X'; } }; \ var caught; \ try { Reflect.get({}, key); caught = 'none'; } catch (e) { caught = e; } \ caught === 'X'", ) .unwrap(); assert!(result.as_bool()); } // 守卫序钉:defineProperty 键转换先于 descriptor 类型检——descriptor 缺省且 // 键抛 "X" 时捕获的必须是键异常原值,不是 descriptor TypeError。 #[test] fn reflect_define_property_key_evaluates_before_descriptor_check() { let mut vm = Vm::new(); let result = eval( &mut vm, "var key = { toString: function() { throw 'X'; } }; \ var caught; \ try { Reflect.defineProperty({}, key, undefined); caught = 'none'; } catch (e) { caught = e; } \ caught === 'X'", ) .unwrap(); assert!(result.as_bool()); } // 227.1 回归守卫:隐式 super 面经 `new` 直接构造不回归。 #[test] fn construct_direct_new_derived_array_guard() { let mut vm = Vm::new(); let result = eval( &mut vm, "class B extends Array { constructor(x) { super(x); } } \ var sub = new B(2); \ class Sub extends Array { constructor(x) { super(x); } } \ var s7 = new Sub(7); \ sub instanceof B && sub.length === 2 && s7.length === 7", ) .unwrap(); assert!(result.as_bool()); } // 数组 length 是虚拟自身属性:ownKeys 注入字符串组首(创建序第一枚字符串键)。 #[test] fn reflect_own_keys_array_includes_virtual_length() { let mut vm = Vm::new(); let result = eval( &mut vm, "var k1 = Reflect.ownKeys([]); \ var k2 = Reflect.ownKeys([,,2]); \ var a = []; a.x = 1; var k3 = Reflect.ownKeys(a); \ k1.join(',') === 'length' && k2.join(',') === '2,length' && k3.join(',') === 'length,x'", ) .unwrap(); assert!(result.as_bool()); } // array index 上限 2^32-2:4294967294 落索引组(整数升序在前), // 4294967295 落字符串组(创建序)。 #[test] fn reflect_own_keys_large_index_boundary() { let mut vm = Vm::new(); let result = eval( &mut vm, "var o = { b: 1, a: 2, 4294967294: 3, 4294967295: 4 }; \ Reflect.ownKeys(o).join(',')", ) .unwrap(); assert_eq!(to_str(&vm, result), "4294967294,b,a,4294967295"); } // Reflect.get 的 own 与 inherited 访问器异常两臂均原值传播。 #[test] fn reflect_get_propagates_accessor_exception_original_value() { let mut vm = Vm::new(); let result = eval( &mut vm, "var boom = { value: 1 }; \ var own = { get p() { throw boom; } }; \ var caughtOwn; \ try { Reflect.get(own, 'p'); caughtOwn = 'none'; } catch (e) { caughtOwn = e; } \ var inherited = { q: 1 }; \ Object.defineProperty(inherited, 'q', { get() { throw boom; }, configurable: true }); \ var sub = Object.create(inherited); \ var caughtInh; \ try { Reflect.get(sub, 'q'); caughtInh = 'none'; } catch (e) { caughtInh = e; } \ caughtOwn === boom && caughtInh === boom", ) .unwrap(); assert!(result.as_bool()); } // apply 的 argumentsList 按 CreateListFromArrayLike 读取:length 经 getter, // 逐索引规范 Get;函数对象命名槽(prototype/length/name)不被误读。 #[test] fn reflect_apply_arguments_list_array_like() { let mut vm = Vm::new(); let result = eval( &mut vm, "function fn() { return [arguments.length, arguments[0]]; } \ var list = Object.create(null); \ Object.defineProperty(list, 'length', { get: function() { return 1; } }); \ var r = Reflect.apply(fn, null, list); \ r[0] === 1 && r[1] === undefined", ) .unwrap(); assert!(result.as_bool()); } // apply 的 length getter 异常原值传播;非对象 argumentsList 抛 TypeError。 #[test] fn reflect_apply_propagates_length_getter_original_value() { let mut vm = Vm::new(); let result = eval( &mut vm, "var boom = 'X'; \ var list = { get length() { throw boom; } }; \ var caught; \ try { Reflect.apply(function(){}, null, list); caught = 'none'; } catch (e) { caught = e; } \ var thrown; \ try { Reflect.apply(function(){}, null, 42); thrown = 'none'; } catch (e) { thrown = (e instanceof TypeError); } \ caught === boom && thrown === true", ) .unwrap(); assert!(result.as_bool()); } // defineProperty 描述符字段 getter 抛出的异常原值传播(Reflect 与 Object 两侧同通道)。 #[test] fn define_property_propagates_attribute_getter_original_value() { let mut vm = Vm::new(); let result = eval( &mut vm, "var boom = 'X'; \ var desc = { get enumerable() { throw boom; } }; \ var caught; \ try { Reflect.defineProperty({}, 'a', desc); caught = 'none'; } catch (e) { caught = e; } \ var caughtObj; \ try { Object.defineProperty({}, 'a', desc); caughtObj = 'none'; } catch (e) { caughtObj = e; } \ caught === boom && caughtObj === boom", ) .unwrap(); assert!(result.as_bool()); }