Skip to content

Commit

Permalink
Merge 1679573 into 880792e
Browse files Browse the repository at this point in the history
  • Loading branch information
tofpie authored Dec 19, 2020
2 parents 880792e + 1679573 commit f7c7c0b
Show file tree
Hide file tree
Showing 3 changed files with 55 additions and 1 deletion.
29 changes: 29 additions & 0 deletions boa/src/builtins/object/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,7 @@ impl BuiltIn for Object {
.method(Self::has_own_property, "hasOwnProperty", 0)
.method(Self::property_is_enumerable, "propertyIsEnumerable", 0)
.method(Self::to_string, "toString", 0)
.method(Self::is_prototype_of, "isPrototypeOf", 0)
.static_method(Self::create, "create", 2)
.static_method(Self::set_prototype_of, "setPrototypeOf", 2)
.static_method(Self::get_prototype_of, "getPrototypeOf", 1)
Expand Down Expand Up @@ -258,6 +259,34 @@ impl Object {
Ok(obj)
}

/// `Object.prototype.isPrototypeOf( proto )`
///
/// Check whether or not an object exists within another object's prototype chain.
///
/// More information:
/// - [ECMAScript reference][spec]
/// - [MDN documentation][mdn]
///
/// [spec]: https://tc39.es/ecma262/#sec-object.prototype.isprototypeof
/// [mdn]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/isPrototypeOf
pub fn is_prototype_of(this: &Value, args: &[Value], context: &mut Context) -> Result<Value> {
let undefined = Value::undefined();
let mut v = args.get(0).unwrap_or(&undefined).clone();
if !v.is_object() {
return Ok(Value::Boolean(false));
}
let o = Value::from(this.to_object(context)?);
loop {
v = Self::get_prototype_of(this, &[v], context)?;
if v.is_null() {
return Ok(Value::Boolean(false));
}
if same_value(&o, &v) {
return Ok(Value::Boolean(true));
}
}
}

/// 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");
Expand Down
11 changes: 11 additions & 0 deletions boa/src/builtins/object/tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -279,3 +279,14 @@ fn object_define_properties() {

assert_eq!(forward(&mut context, "obj.p"), "42");
}

#[test]
fn object_is_prototype_of() {
let mut context = Context::new();

let init = r#"
Object.prototype.isPrototypeOf(String.prototype)
"#;

assert_eq!(context.eval(init).unwrap(), Value::boolean(true));
}
16 changes: 15 additions & 1 deletion boa/src/object/gcobject.rs
Original file line number Diff line number Diff line change
Expand Up @@ -198,7 +198,21 @@ impl GcObject {
// <https://tc39.es/ecma262/#sec-ecmascript-function-objects-construct-argumentslist-newtarget>
#[track_caller]
pub fn construct(&self, args: &[Value], context: &mut Context) -> Result<Value> {
let this: Value = Object::create(self.get(&PROTOTYPE.into())).into();
// If the prototype of the constructor is not an object, then use the default object
// prototype as prototype for the new object
// see <https://tc39.es/ecma262/#sec-ordinarycreatefromconstructor>
// see <https://tc39.es/ecma262/#sec-getprototypefromconstructor>
let proto = self.get(&PROTOTYPE.into());
let proto = if proto.is_object() {
proto
} else {
context
.standard_objects()
.object_object()
.prototype()
.into()
};
let this: Value = Object::create(proto).into();

let this_function_object = self.clone();
let body = if let Some(function) = self.borrow().as_function() {
Expand Down

0 comments on commit f7c7c0b

Please sign in to comment.