diff --git a/crates/oxide_compiler/src/compiler.rs b/crates/oxide_compiler/src/compiler.rs index 309ebbf6..41d813da 100644 --- a/crates/oxide_compiler/src/compiler.rs +++ b/crates/oxide_compiler/src/compiler.rs @@ -184,6 +184,7 @@ impl CompileCtx { let builtins = [ "NaN", "undefined", + "Infinity", "Object", "Array", "String", diff --git a/crates/oxide_compiler/tests/compile_expr_tests.rs b/crates/oxide_compiler/tests/compile_expr_tests.rs index cdd70d2d..409d383f 100644 --- a/crates/oxide_compiler/tests/compile_expr_tests.rs +++ b/crates/oxide_compiler/tests/compile_expr_tests.rs @@ -376,3 +376,15 @@ fn compile_this_member_read_ok() { let module = compile_source("function f() { return this.x; }"); assert!(!module.bytecode.is_empty()); } + +#[test] +fn compile_infinity_ok() { + let module = compile_source("Infinity"); + assert!(!module.bytecode.is_empty()); +} + +#[test] +fn compile_neg_infinity_ok() { + let module = compile_source("1 / -Infinity"); + assert!(!module.bytecode.is_empty()); +} diff --git a/crates/oxide_kernel/src/kernel.rs b/crates/oxide_kernel/src/kernel.rs index fcfa02e7..58fe2379 100644 --- a/crates/oxide_kernel/src/kernel.rs +++ b/crates/oxide_kernel/src/kernel.rs @@ -88,6 +88,7 @@ impl OxideKernel { let si_nan = string_forge.intern("NaN").0; let si_undef = string_forge.intern("undefined").0; + let si_infinity = string_forge.intern("Infinity").0; let nan_shape = shape_forge.make_shape(EMPTY_SHAPE_ID, si_nan); global_obj.set_shape_id(nan_shape); @@ -101,6 +102,12 @@ impl OxideKernel { .ensure_hash_props() .push(Box::new(JsValue::undefined())); + let inf_shape = shape_forge.make_shape(undef_shape, si_infinity); + global_obj.set_shape_id(inf_shape); + global_obj + .ensure_hash_props() + .push(Box::new(JsValue::float(f64::INFINITY))); + let global_object = P::new(global_obj); Self { diff --git a/crates/oxide_vm/tests/builtins_globals_tests.rs b/crates/oxide_vm/tests/builtins_globals_tests.rs index e5b30516..177078be 100644 --- a/crates/oxide_vm/tests/builtins_globals_tests.rs +++ b/crates/oxide_vm/tests/builtins_globals_tests.rs @@ -37,3 +37,45 @@ fn typeof_undefined_is_undefined() { let result = eval("typeof undefined").unwrap(); assert!(result.is_string()); } + +#[test] +fn eval_infinity_returns_infinity() { + let result = eval("Infinity").unwrap(); + assert!(result.is_double()); + assert!(result.as_double().is_infinite()); + assert!(result.as_double().is_sign_positive()); +} + +#[test] +fn eval_neg_infinity_via_division() { + let result = eval("1 / Infinity").unwrap(); + assert!(result.is_double()); + assert_eq!(result.as_double(), 0.0); +} + +#[test] +fn typeof_infinity_is_number() { + let result = eval("typeof Infinity").unwrap(); + assert!(result.is_string()); +} + +#[test] +fn infinity_ne_nan() { + let result = eval("Infinity !== NaN").unwrap(); + assert!(result.is_bool()); + assert!(result.as_bool()); +} + +#[test] +fn infinity_gt_large_number() { + let result = eval("Infinity > 1e308").unwrap(); + assert!(result.is_bool()); + assert!(result.as_bool()); +} + +#[test] +fn division_by_zero_gives_infinity() { + let result = eval("1 / 0").unwrap(); + assert!(result.is_double()); + assert!(result.as_double().is_infinite()); +}