Skip to content

Commit

Permalink
Implement setter of Object.p.__proto__
Browse files Browse the repository at this point in the history
  • Loading branch information
CYBAI committed Jun 11, 2022
1 parent 8d94cc6 commit 26cb3ab
Showing 1 changed file with 49 additions and 1 deletion.
50 changes: 49 additions & 1 deletion boa_engine/src/builtins/object/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,10 @@ impl BuiltIn for Object {
.name("get __proto__")
.build();

let legacy_setter_proto = FunctionBuilder::native(context, Self::legacy_proto_setter)
.name("set __proto__")
.build();

ConstructorBuilder::with_standard_constructor(
context,
Self::constructor,
Expand All @@ -58,7 +62,7 @@ impl BuiltIn for Object {
.accessor(
"__proto__",
Some(legacy_proto_getter),
None,
Some(legacy_setter_proto),
Attribute::NON_ENUMERABLE | Attribute::CONFIGURABLE,
)
.method(Self::has_own_property, "hasOwnProperty", 1)
Expand Down Expand Up @@ -152,6 +156,50 @@ impl Object {
Ok(proto.map_or(JsValue::Null, JsValue::new))
}

/// `set Object.prototype.__proto__`
///
/// The `__proto__` setter allows the [[Prototype]] of
/// an object to be mutated.
///
/// More information:
/// - [ECMAScript reference][spec]
/// - [MDN documentation][mdn]
///
/// [spec]: https://tc39.es/ecma262/#sec-set-object.prototype.__proto__
/// [mdn]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/proto
pub fn legacy_proto_setter(
this: &JsValue,
args: &[JsValue],
context: &mut Context,
) -> JsResult<JsValue> {
// 1. Let O be ? RequireObjectCoercible(this value).
let this = this.require_object_coercible(context)?;

// 2. If Type(proto) is neither Object nor Null, return undefined.
let proto = match args.get_or_undefined(0) {
JsValue::Object(proto) => Some(proto.clone()),
JsValue::Null => None,
_ => return Ok(JsValue::undefined()),
};

// 3. If Type(O) is not Object, return undefined.
let object = match this {
JsValue::Object(object) => object,
_ => return Ok(JsValue::undefined()),
};

// 4. Let status be ? O.[[SetPrototypeOf]](proto).
let status = object.__set_prototype_of__(proto, context)?;

// 5. If status is false, throw a TypeError exception.
if !status {
return context.throw_type_error("__proto__ called on null or undefined");
}

// 6. Return undefined.
Ok(JsValue::undefined())
}

/// `Object.prototype.__defineGetter__(prop, func)`
///
/// Binds an object's property to a function to be called when that property is looked up.
Expand Down

0 comments on commit 26cb3ab

Please sign in to comment.