Skip to content

Commit

Permalink
fix strict equality and primitive constructors
Browse files Browse the repository at this point in the history
  • Loading branch information
y21 committed Jan 14, 2024
1 parent 67c9864 commit 2e1f336
Show file tree
Hide file tree
Showing 5 changed files with 46 additions and 83 deletions.
9 changes: 7 additions & 2 deletions crates/dash_vm/src/js_std/boolean.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,16 @@ use crate::gc::interner::sym;
use crate::throw;
use crate::value::function::native::CallContext;
use crate::value::ops::conversions::ValueConversion;
use crate::value::{Value, ValueContext};
use crate::value::{boxed, Value, ValueContext};

pub fn constructor(cx: CallContext) -> Result<Value, Value> {
let value = cx.args.get(0).unwrap_or_undefined().to_boolean(cx.scope)?;
Ok(Value::Boolean(value))
if cx.is_constructor_call {
let value = boxed::Boolean::new(cx.scope, value);
Ok(Value::Object(cx.scope.register(value).into()))
} else {
Ok(Value::Boolean(value))
}
}

pub fn to_string(cx: CallContext) -> Result<Value, Value> {
Expand Down
9 changes: 7 additions & 2 deletions crates/dash_vm/src/js_std/number.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,16 @@ use crate::util::format_f64;
use crate::value::function::native::CallContext;
use crate::value::ops::conversions::ValueConversion;
use crate::value::primitive::{Number, MAX_SAFE_INTEGERF};
use crate::value::{Value, ValueContext};
use crate::value::{boxed, Value, ValueContext};

pub fn constructor(cx: CallContext) -> Result<Value, Value> {
let value = cx.args.get(0).unwrap_or_undefined().to_number(cx.scope)?;
Ok(Value::number(value))
if cx.is_constructor_call {
let value = boxed::Number::new(cx.scope, value);
Ok(Value::Object(cx.scope.register(value).into()))
} else {
Ok(Value::number(value))
}
}

pub fn to_string(cx: CallContext) -> Result<Value, Value> {
Expand Down
9 changes: 6 additions & 3 deletions crates/dash_vm/src/value/boxed.rs
Original file line number Diff line number Diff line change
Expand Up @@ -90,9 +90,12 @@ macro_rules! boxed_primitive {
ValueEquality::eq(&self.inner, other, sc)
}

fn strict_eq(&self, other: &Value, sc: &mut LocalScope) -> Result<Value, Value> {
// TODO: compare pointers
ValueEquality::strict_eq(&self.inner, other, sc)
fn strict_eq(&self, other: &Value, _: &mut LocalScope) -> Result<Value, Value> {
if let Value::Object(obj) = other {
Ok(Value::Boolean(std::ptr::eq(self, obj.erased_value().cast::<$name>())))
} else {
Ok(Value::Boolean(false))
}
}

fn ne(&self, other: &Value, sc: &mut LocalScope) -> Result<Value, Value> {
Expand Down
15 changes: 14 additions & 1 deletion crates/dash_vm/src/value/ops/arithmetic.rs
Original file line number Diff line number Diff line change
Expand Up @@ -158,6 +158,19 @@ impl ValueEquality for Value {
}

fn strict_eq(&self, other: &Value, sc: &mut LocalScope) -> Result<Value, Value> {
delegate!(self, other, sc, ValueEquality::strict_eq)
Ok(Value::Boolean(match (self, other) {
(Value::Number(l), Value::Number(r)) => l == r,
(Value::Boolean(l), Value::Boolean(r)) => l == r,
(Value::String(l), Value::String(r)) => l == r,
(Value::Undefined(_), Value::Undefined(_)) => true,
(Value::Null(_), Value::Null(_)) => true,
(Value::Symbol(l), Value::Symbol(r)) => l == r,
(Value::Object(l), Value::Object(r)) => l == r,
(Value::External(l), Value::External(r)) => {
// TODO: this branch should be unreachable, check if true
matches!(l.inner().strict_eq(r.inner(), sc)?, Value::Boolean(true))
}
_ => false,
}))
}
}
87 changes: 12 additions & 75 deletions crates/dash_vm/src/value/primitive.rs
Original file line number Diff line number Diff line change
Expand Up @@ -480,8 +480,8 @@ impl ValueEquality for f64 {
other.to_number(sc).map(|other| Value::Boolean(*self == other))
}

fn strict_eq(&self, other: &Value, sc: &mut LocalScope) -> Result<Value, Value> {
ValueEquality::eq(self, other, sc)
fn strict_eq(&self, other: &Value, _: &mut LocalScope) -> Result<Value, Value> {
Ok(Value::Boolean(other == &Value::number(*self)))
}
}

Expand Down Expand Up @@ -551,8 +551,8 @@ impl ValueEquality for bool {
other.to_boolean(sc).map(|other| Value::Boolean(*self == other))
}

fn strict_eq(&self, other: &Value, sc: &mut LocalScope) -> Result<Value, Value> {
ValueEquality::eq(self, other, sc)
fn strict_eq(&self, other: &Value, _: &mut LocalScope) -> Result<Value, Value> {
Ok(Value::Boolean(other == &Value::Boolean(*self)))
}
}

Expand Down Expand Up @@ -583,69 +583,6 @@ impl ValueConversion for bool {
}
}

// impl PrimitiveCapabilities for Rc<str> {
// fn as_string(&self) -> Option<JsString> {
// Some(self.clone())
// }

// fn unbox(&self) -> Value {
// Value::String(Rc::clone(self))
// }
// }

// impl ValueEquality for Rc<str> {
// fn lt(&self, other: &Value, sc: &mut LocalScope) -> Result<Value, Value> {
// other.to_js_string(sc).map(|other| Value::Boolean(self < &other))
// }

// fn le(&self, other: &Value, sc: &mut LocalScope) -> Result<Value, Value> {
// other.to_js_string(sc).map(|other| Value::Boolean(self <= &other))
// }

// fn gt(&self, other: &Value, sc: &mut LocalScope) -> Result<Value, Value> {
// other.to_js_string(sc).map(|other| Value::Boolean(self > &other))
// }

// fn ge(&self, other: &Value, sc: &mut LocalScope) -> Result<Value, Value> {
// other.to_js_string(sc).map(|other| Value::Boolean(self >= &other))
// }

// fn eq(&self, other: &Value, sc: &mut LocalScope) -> Result<Value, Value> {
// other.to_js_string(sc).map(|other| Value::Boolean(self == &other))
// }

// fn strict_eq(&self, other: &Value, sc: &mut LocalScope) -> Result<Value, Value> {
// ValueEquality::eq(self, other, sc)
// }
// }

// impl ValueConversion for Rc<str> {
// fn to_primitive(&self, _sc: &mut LocalScope, _preferred_type: Option<PreferredType>) -> Result<Value, Value> {
// Ok(Value::String(Rc::clone(self)))
// }

// fn to_number(&self, _sc: &mut LocalScope) -> Result<f64, Value> {
// Ok(self.parse().unwrap_or(f64::NAN))
// }

// fn to_boolean(&self) -> Result<bool, Value> {
// Ok(!self.is_empty())
// }

// fn to_js_string(&self, _sc: &mut LocalScope) -> Result<Rc<str>, Value> {
// Ok(Rc::clone(self))
// }

// fn length_of_array_like(&self, _sc: &mut LocalScope) -> Result<usize, Value> {
// Ok(self.len())
// }

// fn to_object(&self, sc: &mut LocalScope) -> Result<Handle, Value> {
// let bool = BoxedString::new(sc, self.clone());
// Ok(sc.register(bool))
// }
// }

impl PrimitiveCapabilities for Undefined {
fn is_undefined(&self) -> bool {
true
Expand Down Expand Up @@ -689,8 +626,8 @@ impl ValueEquality for Undefined {
}
}

fn strict_eq(&self, other: &Value, sc: &mut LocalScope) -> Result<Value, Value> {
ValueEquality::eq(self, other, sc)
fn strict_eq(&self, other: &Value, _: &mut LocalScope) -> Result<Value, Value> {
Ok(Value::Boolean(matches!(other, Value::Undefined(_))))
}
}

Expand Down Expand Up @@ -751,8 +688,8 @@ impl ValueEquality for Null {
other.to_number(sc).map(|other| Value::Boolean(0.0 == other))
}

fn strict_eq(&self, other: &Value, sc: &mut LocalScope) -> Result<Value, Value> {
ValueEquality::eq(self, other, sc)
fn strict_eq(&self, other: &Value, _: &mut LocalScope) -> Result<Value, Value> {
Ok(Value::Boolean(matches!(other, Value::Null(_))))
}
}

Expand Down Expand Up @@ -809,8 +746,8 @@ impl ValueEquality for Symbol {
other.to_number(sc).map(|other| Value::Boolean(0.0 == other))
}

fn strict_eq(&self, other: &Value, sc: &mut LocalScope) -> Result<Value, Value> {
ValueEquality::eq(self, other, sc)
fn strict_eq(&self, other: &Value, _: &mut LocalScope) -> Result<Value, Value> {
Ok(Value::Boolean(other == &Value::Symbol(self.clone())))
}
}

Expand Down Expand Up @@ -941,8 +878,8 @@ impl ValueEquality for Number {
ValueEquality::eq(&self.0, other, sc)
}

fn strict_eq(&self, other: &Value, sc: &mut LocalScope) -> Result<Value, Value> {
ValueEquality::strict_eq(&self.0, other, sc)
fn strict_eq(&self, other: &Value, _: &mut LocalScope) -> Result<Value, Value> {
Ok(Value::Boolean(other == &Value::Number(*self)))
}
}

Expand Down

0 comments on commit 2e1f336

Please sign in to comment.