Skip to content

Commit

Permalink
Fix Object.defineProperty() (#1005)
Browse files Browse the repository at this point in the history
- Fix panic if first argument is not supplied.
 - Fix panic if second argument is not supplied.
 - Fix bug when the object is not a object.
 - Implemented `DefinePropertyOrThrow()`
  • Loading branch information
HalidOdat committed Jan 1, 2021
1 parent 4cede75 commit 4625c1a
Show file tree
Hide file tree
Showing 2 changed files with 44 additions and 13 deletions.
28 changes: 16 additions & 12 deletions boa/src/builtins/object/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -287,19 +287,23 @@ impl Object {

/// Define a property in an object
pub fn define_property(_: &Value, args: &[Value], context: &mut Context) -> Result<Value> {
let obj = args.get(0).expect("Cannot get object");
let prop = args
.get(1)
.expect("Cannot get object")
.to_property_key(context)?;

let desc = if let Value::Object(ref object) = args.get(2).cloned().unwrap_or_default() {
object.to_property_descriptor(context)?
let object = args.get(0).cloned().unwrap_or_else(Value::undefined);
if let Some(mut object) = object.as_object() {
let key = args
.get(1)
.unwrap_or(&Value::undefined())
.to_property_key(context)?;
let desc = args
.get(2)
.unwrap_or(&Value::undefined())
.to_property_descriptor(context)?;

object.define_property_or_throw(key, desc, context)?;

Ok(object.into())
} else {
return context.throw_type_error("Property description must be an object");
};
obj.set_property(prop, desc);
Ok(obj.clone())
context.throw_type_error("Object.defineProperty called on non-object")
}
}

/// `Object.defineProperties( proto, [propertiesObject] )`
Expand Down
29 changes: 28 additions & 1 deletion boa/src/object/gcobject.rs
Original file line number Diff line number Diff line change
Expand Up @@ -761,7 +761,6 @@ impl GcObject {
Ok(false)
}
}

#[inline]
#[track_caller]
pub fn has_own_property<K>(&self, key: K) -> bool
Expand All @@ -771,6 +770,34 @@ impl GcObject {
let key = key.into();
self.get_own_property(&key).is_some()
}

/// Defines the property or throws a `TypeError` if the operation fails.
///
/// More information:
/// - [EcmaScript reference][spec]
///
/// [spec]: https://tc39.es/ecma262/#sec-definepropertyorthrow
#[inline]
pub(crate) fn define_property_or_throw<K, P>(
&mut self,
key: K,
desc: P,
context: &mut Context,
) -> Result<()>
where
K: Into<PropertyKey>,
P: Into<PropertyDescriptor>,
{
let key = key.into();
let desc = desc.into();

let success = self.define_own_property(key.clone(), desc);
if !success {
Err(context.construct_type_error(format!("Cannot redefine property: {}", key)))
} else {
Ok(())
}
}
}

impl AsRef<GcCell<Object>> for GcObject {
Expand Down

0 comments on commit 4625c1a

Please sign in to comment.