static function abstract_equal($a, $b) { if ($a->type != $b->type) { if ($a->type == js_val::UNDEFINED and $b->type == js_val::NULL) { return jsrt::$true; } if ($b->type == js_val::UNDEFINED and $a->type == js_val::NULL) { return jsrt::$true; } if ($a->type == js_val::NUMBER and $b->type == js_val::STRING) { return jsrt::abstract_equal($a, $b->toNumber()); } if ($b->type == js_val::NUMBER and $a->type == js_val::STRING) { return jsrt::abstract_equal($a->toNumber(), $b); } if ($a->type == js_val::BOOLEAN) { return jsrt::abstract_equal($a->toNumber(), $b); } if ($b->type == js_val::BOOLEAN) { return jsrt::abstract_equal($a, $b->toNumber()); } if (($a->type == js_val::NUMBER or $a->type == js_val::STRING) and $b->type == js_val::OBJECT) { return jsrt::abstract_equal($a, $b->toPrimitive()); } if (($b->type == js_val::NUMBER or $b->type == js_val::STRING) and $a->type == js_val::OBJECT) { return jsrt::abstract_equal($a->toPrimitive(), $b); } return jsrt::$false; } else { if ($a->type == js_val::UNDEFINED) { return jsrt::$true; } if ($a->type == js_val::NULL) { return jsrt::$true; } if ($a->type == js_val::NUMBER) { if (is_nan($a->value) or is_nan($b->value)) { return jsrt::$false; } } if ($a->type == js_val::OBJECT) { return $a === $b ? jsrt::$true : jsrt::$false; } return $a->value == $b->value ? jsrt::$true : jsrt::$false; } }