Replace `as_bool` with `coerce_to_bool`.
Functions that need to assert Boolness without coercion should either: 1. Ensure their function declaration requires a Boolean. (We don't enforce type errors on ES4 typehints yet, but we should.) 2. Check the value type themselves and raise their own errors if necessary. As it stands the only users of `as_bool` either needed to check the type themselves or use `coerce_to_bool`. Notably, `setPropertyIsEnumerable` doesn't appear to coerce *or* throw an error: it instead fails silently if you hand it a non-`Boolean` value.
This commit is contained in:
parent
95ca978034
commit
5bb8c1836f
|
@ -1321,7 +1321,7 @@ impl<'a, 'gc, 'gc_context> Activation<'a, 'gc, 'gc_context> {
|
||||||
offset: i32,
|
offset: i32,
|
||||||
reader: &mut Reader<Cursor<&[u8]>>,
|
reader: &mut Reader<Cursor<&[u8]>>,
|
||||||
) -> Result<FrameControl<'gc>, Error> {
|
) -> Result<FrameControl<'gc>, Error> {
|
||||||
let value = self.context.avm2.pop().as_bool()?;
|
let value = self.context.avm2.pop().coerce_to_boolean();
|
||||||
|
|
||||||
if value {
|
if value {
|
||||||
reader.seek(offset as i64)?;
|
reader.seek(offset as i64)?;
|
||||||
|
@ -1335,7 +1335,7 @@ impl<'a, 'gc, 'gc_context> Activation<'a, 'gc, 'gc_context> {
|
||||||
offset: i32,
|
offset: i32,
|
||||||
reader: &mut Reader<Cursor<&[u8]>>,
|
reader: &mut Reader<Cursor<&[u8]>>,
|
||||||
) -> Result<FrameControl<'gc>, Error> {
|
) -> Result<FrameControl<'gc>, Error> {
|
||||||
let value = self.context.avm2.pop().as_bool()?;
|
let value = self.context.avm2.pop().coerce_to_boolean();
|
||||||
|
|
||||||
if !value {
|
if !value {
|
||||||
reader.seek(offset as i64)?;
|
reader.seek(offset as i64)?;
|
||||||
|
|
|
@ -124,16 +124,17 @@ pub fn set_property_is_enumerable<'gc>(
|
||||||
let this = this?;
|
let this = this?;
|
||||||
let name: Result<&Value<'gc>, Error> = args.get(0).ok_or_else(|| "No name specified".into());
|
let name: Result<&Value<'gc>, Error> = args.get(0).ok_or_else(|| "No name specified".into());
|
||||||
let name = name?.as_string()?;
|
let name = name?.as_string()?;
|
||||||
let is_enum = args
|
|
||||||
.get(1)
|
|
||||||
.cloned()
|
|
||||||
.unwrap_or(Value::Bool(true))
|
|
||||||
.as_bool()?;
|
|
||||||
|
|
||||||
if let Some(ns) = this.resolve_any(name)? {
|
if let Some(Value::Bool(is_enum)) = args.get(1) {
|
||||||
if !ns.is_private() {
|
if let Some(ns) = this.resolve_any(name)? {
|
||||||
let qname = QName::new(ns, name);
|
if !ns.is_private() {
|
||||||
this.set_local_property_is_enumerable(activation.context.gc_context, &qname, is_enum)?;
|
let qname = QName::new(ns, name);
|
||||||
|
this.set_local_property_is_enumerable(
|
||||||
|
activation.context.gc_context,
|
||||||
|
&qname,
|
||||||
|
*is_enum,
|
||||||
|
)?;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -225,18 +225,25 @@ impl<'gc> Value<'gc> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn as_bool(&self) -> Result<bool, Error> {
|
|
||||||
if let Value::Bool(b) = self {
|
|
||||||
Ok(*b)
|
|
||||||
} else {
|
|
||||||
Err(format!("Expected Boolean, found {:?}", self).into())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn as_namespace(&self) -> Result<&Namespace<'gc>, Error> {
|
pub fn as_namespace(&self) -> Result<&Namespace<'gc>, Error> {
|
||||||
match self {
|
match self {
|
||||||
Value::Namespace(ns) => Ok(ns),
|
Value::Namespace(ns) => Ok(ns),
|
||||||
_ => Err(format!("Expected Namespace, found {:?}", self).into()),
|
_ => Err(format!("Expected Namespace, found {:?}", self).into()),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Coerce the value to a boolean.
|
||||||
|
///
|
||||||
|
/// Boolean coercion happens according to the rules specified in the ES4
|
||||||
|
/// draft proposals, which appear to be identical to ECMA-262 Edition 3.
|
||||||
|
pub fn coerce_to_boolean(&self) -> bool {
|
||||||
|
match self {
|
||||||
|
Value::Undefined | Value::Null => false,
|
||||||
|
Value::Bool(b) => *b,
|
||||||
|
Value::Number(f) => !f.is_nan() && f.abs() != 0.0,
|
||||||
|
Value::String(s) => !s.is_empty(),
|
||||||
|
Value::Namespace(_) => true,
|
||||||
|
Value::Object(_) => true,
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue