Allow no-hint primitive coercion
This commit is contained in:
parent
76ab8570e4
commit
2ef03c6019
|
@ -486,10 +486,10 @@ impl<'a, 'gc, 'gc_context> Activation<'a, 'gc, 'gc_context> {
|
|||
Op::IfFalse { offset } => self.op_if_false(offset, reader),
|
||||
Op::IfStrictEq { offset } => self.op_if_strict_eq(offset, reader),
|
||||
Op::IfStrictNe { offset } => self.op_if_strict_ne(offset, reader),
|
||||
Op::IfEq { offset } => self.op_if_eq(context, offset, reader),
|
||||
Op::IfNe { offset } => self.op_if_ne(context, offset, reader),
|
||||
Op::IfEq { offset } => self.op_if_eq(offset, reader),
|
||||
Op::IfNe { offset } => self.op_if_ne(offset, reader),
|
||||
Op::StrictEquals => self.op_strict_equals(),
|
||||
Op::Equals => self.op_equals(context),
|
||||
Op::Equals => self.op_equals(),
|
||||
Op::Not => self.op_not(),
|
||||
Op::HasNext => self.op_has_next(),
|
||||
Op::HasNext2 {
|
||||
|
@ -1450,14 +1450,13 @@ impl<'a, 'gc, 'gc_context> Activation<'a, 'gc, 'gc_context> {
|
|||
|
||||
fn op_if_eq(
|
||||
&mut self,
|
||||
context: &mut UpdateContext<'_, 'gc, '_>,
|
||||
offset: i32,
|
||||
reader: &mut Reader<Cursor<&[u8]>>,
|
||||
) -> Result<FrameControl<'gc>, Error> {
|
||||
let value2 = self.avm2.pop();
|
||||
let value1 = self.avm2.pop();
|
||||
let value2 = self.context.avm2.pop();
|
||||
let value1 = self.context.avm2.pop();
|
||||
|
||||
if value1.abstract_eq(&value2, self, context)? {
|
||||
if value1.abstract_eq(&value2, self)? {
|
||||
reader.seek(offset as i64)?;
|
||||
}
|
||||
|
||||
|
@ -1466,14 +1465,13 @@ impl<'a, 'gc, 'gc_context> Activation<'a, 'gc, 'gc_context> {
|
|||
|
||||
fn op_if_ne(
|
||||
&mut self,
|
||||
context: &mut UpdateContext<'_, 'gc, '_>,
|
||||
offset: i32,
|
||||
reader: &mut Reader<Cursor<&[u8]>>,
|
||||
) -> Result<FrameControl<'gc>, Error> {
|
||||
let value2 = self.avm2.pop();
|
||||
let value1 = self.avm2.pop();
|
||||
let value2 = self.context.avm2.pop();
|
||||
let value1 = self.context.avm2.pop();
|
||||
|
||||
if !value1.abstract_eq(&value2, self, context)? {
|
||||
if !value1.abstract_eq(&value2, self)? {
|
||||
reader.seek(offset as i64)?;
|
||||
}
|
||||
|
||||
|
@ -1489,16 +1487,13 @@ impl<'a, 'gc, 'gc_context> Activation<'a, 'gc, 'gc_context> {
|
|||
Ok(FrameControl::Continue)
|
||||
}
|
||||
|
||||
fn op_equals(
|
||||
&mut self,
|
||||
context: &mut UpdateContext<'_, 'gc, '_>,
|
||||
) -> Result<FrameControl<'gc>, Error> {
|
||||
let value2 = self.avm2.pop();
|
||||
let value1 = self.avm2.pop();
|
||||
fn op_equals(&mut self) -> Result<FrameControl<'gc>, Error> {
|
||||
let value2 = self.context.avm2.pop();
|
||||
let value1 = self.context.avm2.pop();
|
||||
|
||||
let result = value1.abstract_eq(&value2, self, context)?;
|
||||
let result = value1.abstract_eq(&value2, self)?;
|
||||
|
||||
self.avm2.push(result);
|
||||
self.context.avm2.push(result);
|
||||
|
||||
Ok(FrameControl::Continue)
|
||||
}
|
||||
|
|
|
@ -278,9 +278,12 @@ impl<'gc> Value<'gc> {
|
|||
/// ToPrimitive algorithm which appears to match AVM2.
|
||||
pub fn coerce_to_primitive(
|
||||
&self,
|
||||
hint: Hint,
|
||||
hint: Option<Hint>,
|
||||
activation: &mut Activation<'_, 'gc, '_>,
|
||||
) -> Result<Value<'gc>, Error> {
|
||||
// TODO: `Date` is default-hinted as a `String` for some reason
|
||||
let hint = hint.unwrap_or(Hint::Number);
|
||||
|
||||
match self {
|
||||
Value::Object(o) if hint == Hint::String => {
|
||||
let mut prim = self.clone();
|
||||
|
@ -408,7 +411,7 @@ impl<'gc> Value<'gc> {
|
|||
))
|
||||
.coerce_to_number(activation)?,
|
||||
Value::Object(_) => self
|
||||
.coerce_to_primitive(Hint::Number, activation)?
|
||||
.coerce_to_primitive(Some(Hint::Number), activation)?
|
||||
.coerce_to_number(activation)?,
|
||||
})
|
||||
}
|
||||
|
@ -517,7 +520,7 @@ impl<'gc> Value<'gc> {
|
|||
Value::String(s) => *s,
|
||||
Value::Namespace(ns) => ns.as_uri(),
|
||||
Value::Object(_) => self
|
||||
.coerce_to_primitive(Hint::String, activation)?
|
||||
.coerce_to_primitive(Some(Hint::String), activation)?
|
||||
.coerce_to_string(activation)?,
|
||||
})
|
||||
}
|
||||
|
@ -546,8 +549,7 @@ impl<'gc> Value<'gc> {
|
|||
pub fn abstract_eq(
|
||||
&self,
|
||||
other: &Value<'gc>,
|
||||
activation: &mut Activation<'_, 'gc>,
|
||||
context: &mut UpdateContext<'_, 'gc, '_>,
|
||||
activation: &mut Activation<'_, 'gc, '_>,
|
||||
) -> Result<bool, Error> {
|
||||
match (self, other) {
|
||||
(Value::Undefined, Value::Undefined) => Ok(true),
|
||||
|
@ -573,49 +575,48 @@ impl<'gc> Value<'gc> {
|
|||
(Value::Undefined, Value::Null) => Ok(true),
|
||||
(Value::Null, Value::Undefined) => Ok(true),
|
||||
(Value::Number(_), Value::String(_)) => {
|
||||
let number_other = Value::from(other.coerce_to_number(activation, context)?);
|
||||
let number_other = Value::from(other.coerce_to_number(activation)?);
|
||||
|
||||
self.abstract_eq(&number_other, activation, context)
|
||||
self.abstract_eq(&number_other, activation)
|
||||
}
|
||||
(Value::String(_), Value::Number(_)) => {
|
||||
let number_self = Value::from(self.coerce_to_number(activation, context)?);
|
||||
let number_self = Value::from(self.coerce_to_number(activation)?);
|
||||
|
||||
number_self.abstract_eq(other, activation, context)
|
||||
number_self.abstract_eq(other, activation)
|
||||
}
|
||||
(Value::Bool(_), _) => {
|
||||
let number_self = Value::from(self.coerce_to_number(activation, context)?);
|
||||
let number_self = Value::from(self.coerce_to_number(activation)?);
|
||||
|
||||
number_self.abstract_eq(other, activation, context)
|
||||
number_self.abstract_eq(other, activation)
|
||||
}
|
||||
(_, Value::Bool(_)) => {
|
||||
let number_other = Value::from(other.coerce_to_number(activation, context)?);
|
||||
let number_other = Value::from(other.coerce_to_number(activation)?);
|
||||
|
||||
self.abstract_eq(&number_other, activation, context)
|
||||
self.abstract_eq(&number_other, activation)
|
||||
}
|
||||
(Value::String(_), Value::Object(_)) | (Value::Number(_), Value::Object(_)) => {
|
||||
//TODO: Should this be `Hint::Number`, `Hint::String`, or no-hint?
|
||||
let primitive_other =
|
||||
other.coerce_to_primitive(Hint::Number, activation, context)?;
|
||||
let primitive_other = other.coerce_to_primitive(Some(Hint::Number), activation)?;
|
||||
|
||||
self.abstract_eq(&primitive_other, activation, context)
|
||||
self.abstract_eq(&primitive_other, activation)
|
||||
}
|
||||
(Value::Object(_), Value::String(_)) | (Value::Object(_), Value::Number(_)) => {
|
||||
//TODO: Should this be `Hint::Number`, `Hint::String`, or no-hint?
|
||||
let primitive_self = self.coerce_to_primitive(Hint::Number, activation, context)?;
|
||||
let primitive_self = self.coerce_to_primitive(Some(Hint::Number), activation)?;
|
||||
|
||||
primitive_self.abstract_eq(other, activation, context)
|
||||
primitive_self.abstract_eq(other, activation)
|
||||
}
|
||||
//TODO: This is entirely a shot in the dark.
|
||||
(Value::Namespace(_), _) => {
|
||||
let string_self = self.coerce_to_primitive(Hint::String, activation, context)?;
|
||||
let string_self = self.coerce_to_primitive(Some(Hint::String), activation)?;
|
||||
|
||||
string_self.abstract_eq(other, activation, context)
|
||||
string_self.abstract_eq(other, activation)
|
||||
}
|
||||
//TODO: So is this.
|
||||
(_, Value::Namespace(_)) => {
|
||||
let string_other = other.coerce_to_primitive(Hint::String, activation, context)?;
|
||||
let string_other = other.coerce_to_primitive(Some(Hint::String), activation)?;
|
||||
|
||||
self.abstract_eq(&string_other, activation, context)
|
||||
self.abstract_eq(&string_other, activation)
|
||||
}
|
||||
_ => Ok(false),
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue