diff --git a/crates/oxide_builtins/src/function.rs b/crates/oxide_builtins/src/function.rs index 341256d9..e4eebc01 100644 --- a/crates/oxide_builtins/src/function.rs +++ b/crates/oxide_builtins/src/function.rs @@ -82,18 +82,17 @@ pub fn function_apply(vm: &mut H, args: &[u8]) -> NativeResult { pub fn function_bind(vm: &mut H, args: &[u8]) -> NativeResult { if args.is_empty() { - return NativeResult::Err(JsValue::undefined()); + return NativeResult::Err(crate::error::create_type_error(vm, "Function.prototype.bind called on null or undefined")); } let target_val = vm.reg(args[0]); - if !target_val.is_object() { - return NativeResult::Err(JsValue::undefined()); + if !target_val.is_object() || target_val.as_js_object_ptr().is_null() || !unsafe { &*target_val.as_js_object_ptr() }.is_function() { + return NativeResult::Err(crate::error::create_type_error(vm, "Function.prototype.bind called on non-function")); } let bound_this = if args.len() > 1 { vm.reg(args[1]) } else { JsValue::undefined() }; let wrapper = vm.alloc_object(JsObject::new_empty(EMPTY_SHAPE_ID, JsValue::null())); unsafe { (*wrapper).set_function(true); - // SAFETY: bind_dispatcher is a NativeFn fn-item; valid to store as NativeFnPtr. (*wrapper).set_native_fn(Some(NativeFnPtr::from_raw(bind_dispatcher:: as *const ()))); (*wrapper).set_native_arg_count(0); (*wrapper).ensure_hash_props().push(target_val); diff --git a/crates/oxide_test262/src/main.rs b/crates/oxide_test262/src/main.rs index 73dd1f91..55f2df6b 100644 --- a/crates/oxide_test262/src/main.rs +++ b/crates/oxide_test262/src/main.rs @@ -356,10 +356,7 @@ fn is_skipped(meta: &TestMeta) -> Option { "module" => return Some("module tests excluded".into()), "async" => return Some("async tests excluded".into()), "raw" => return Some("raw tests excluded".into()), - // Engine is strict-mode only; tests that require non-strict semantics - // (e.g. global var ↔ global object binding, arguments.callee, etc.) are - // architecturally incompatible and must be skipped rather than failed. - "noStrict" => return Some("non-strict-mode tests excluded (engine is strict-only)".into()), + // Let noStrict tests run — many pass despite strict mode; runtime skip catches failures _ => {} } } @@ -388,8 +385,10 @@ fn is_skipped(meta: &TestMeta) -> Option { } } - if meta.description.contains("generator") || meta.description.contains("async") { - return Some("description matches excluded pattern".into()); + // Only skip if BOTH description AND features indicate generators/async + // (many tests with "async" in description test non-async functionality) + if meta.description.contains("generator") && meta.features.iter().any(|f| f.contains("generator")) { + return Some("generator description + feature excluded".into()); } None @@ -974,11 +973,7 @@ fn process_path( if !no_skip { let path_str = path.to_string_lossy().replace('\\', "/"); - if path_str.contains("built-ins/Promise/") { - return TestResult::skip(path.to_path_buf(), "Promise tests excluded".into()); - } - if path_str.contains("/dstr/") - || path_str.contains("/eval/") + if path_str.contains("/eval/") || path_str.contains("/function-ctor/") || path_str.contains("/realm/") {