Skip to content

Commit

Permalink
Merge 21fc349 into 553ea52
Browse files Browse the repository at this point in the history
  • Loading branch information
Razican authored Jan 3, 2021
2 parents 553ea52 + 21fc349 commit b3f8f6d
Show file tree
Hide file tree
Showing 4 changed files with 77 additions and 16 deletions.
68 changes: 58 additions & 10 deletions boa/src/builtins/object/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ use crate::{
property::Attribute,
property::DataDescriptor,
property::PropertyDescriptor,
value::{same_value, Value},
value::{same_value, Type, Value},
BoaProfiler, Context, Result,
};

Expand Down Expand Up @@ -243,18 +243,66 @@ impl Object {
}

/// Get the `prototype` of an object.
pub fn get_prototype_of(_: &Value, args: &[Value], _: &mut Context) -> Result<Value> {
let obj = args.get(0).expect("Cannot get object");
Ok(obj
.as_object()
.map_or_else(Value::undefined, |object| object.prototype_instance()))
pub fn get_prototype_of(_: &Value, args: &[Value], ctx: &mut Context) -> Result<Value> {
if args.is_empty() {
return ctx.throw_type_error(
"Object.getPrototypeOf: At least 1 argument required, but only 0 passed",
);
}

// 1. Let obj be ? ToObject(O).
let obj = args[0].clone().to_object(ctx)?;

// 2. Return ? obj.[[GetPrototypeOf]]().
Ok(obj.prototype_instance())
}

/// Set the `prototype` of an object.
pub fn set_prototype_of(_: &Value, args: &[Value], _: &mut Context) -> Result<Value> {
let obj = args.get(0).expect("Cannot get object").clone();
let proto = args.get(1).expect("Cannot get object").clone();
obj.as_object().unwrap().set_prototype_instance(proto);
///
/// [More information][spec]
///
/// [spec]: https://tc39.es/ecma262/#sec-object.setprototypeof
pub fn set_prototype_of(_: &Value, args: &[Value], ctx: &mut Context) -> Result<Value> {
if args.len() < 2 {
return ctx.throw_type_error(format!(
"Object.setPrototypeOf: At least 2 arguments required, but only {} passed",
args.len()
));
}

// 1. Set O to ? RequireObjectCoercible(O).
let obj = args
.get(0)
.cloned()
.unwrap_or_default()
.require_object_coercible(ctx)?.clone();

// 2. If Type(proto) is neither Object nor Null, throw a TypeError exception.
let proto = args.get(1).cloned().unwrap_or_default();
if !matches!(proto.get_type(), Type::Object | Type::Null) {
return ctx.throw_type_error(format!(
"expected an object or null, got {}",
proto.get_type().as_str()
));
}

// 3. If Type(O) is not Object, return O.
if obj.get_type() != Type::Object {
return Ok(obj);
}

// 4. Let status be ? O.[[SetPrototypeOf]](proto).
let status = obj
.as_object()
.expect("obj was not an object")
.set_prototype_instance(proto);

// 5. If status is false, throw a TypeError exception.
if !status {
return ctx.throw_type_error("can't set prototype of this object");
}

// 6. Return O.
Ok(obj)
}

Expand Down
2 changes: 1 addition & 1 deletion boa/src/object/gcobject.rs
Original file line number Diff line number Diff line change
Expand Up @@ -550,7 +550,7 @@ impl GcObject {
/// or if th prototype is not an object or undefined.
#[inline]
#[track_caller]
pub fn set_prototype_instance(&mut self, prototype: Value) {
pub fn set_prototype_instance(&mut self, prototype: Value) -> bool {
self.borrow_mut().set_prototype_instance(prototype)
}

Expand Down
20 changes: 16 additions & 4 deletions boa/src/object/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ use crate::{
context::StandardConstructor,
gc::{Finalize, Trace},
property::{Attribute, DataDescriptor, PropertyDescriptor, PropertyKey},
value::{RcBigInt, RcString, RcSymbol, Value},
value::{same_value, RcBigInt, RcString, RcSymbol, Value},
BoaProfiler, Context,
};
use rustc_hash::FxHashMap;
Expand Down Expand Up @@ -483,11 +483,23 @@ impl Object {
&self.prototype
}

#[track_caller]
/// Sets the prototype instance of the object.
///
/// [More information][spec]
///
/// [spec]: https://tc39.es/ecma262/#sec-invariants-of-the-essential-internal-methods
#[inline]
pub fn set_prototype_instance(&mut self, prototype: Value) {
#[track_caller]
pub fn set_prototype_instance(&mut self, prototype: Value) -> bool {
assert!(prototype.is_null() || prototype.is_object());
self.prototype = prototype
if self.extensible {
self.prototype = prototype;
true
} else {
// If target is non-extensible, [[SetPrototypeOf]] must return false
// unless V is the SameValue as the target's observed [[GetPrototypeOf]] value.
same_value(&prototype, &self.prototype)
}
}

/// Similar to `Value::new_object`, but you can pass a prototype to create from, plus a kind
Expand Down
3 changes: 2 additions & 1 deletion boa/src/value/display.rs
Original file line number Diff line number Diff line change
Expand Up @@ -110,7 +110,8 @@ pub(crate) fn log_string_from(x: &Value, print_internals: bool, print_children:
.unwrap()
.value()
.as_number()
.unwrap() as i32;
.map(|n| n as i32)
.unwrap_or_default();

if print_children {
if len == 0 {
Expand Down

0 comments on commit b3f8f6d

Please sign in to comment.