Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Implement Object.getOwnPropertyNames and Object.getOwnPropertySymbols #1606

Merged
81 changes: 81 additions & 0 deletions boa/src/builtins/object/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -85,6 +85,8 @@ impl BuiltIn for Object {
"getOwnPropertyDescriptors",
1,
)
.static_method(Self::get_own_property_names, "getOwnPropertyNames", 1)
.static_method(Self::get_own_property_symbols, "getOwnPropertySymbols", 1)
.build();

(Self::NAME, object.into(), Self::attribute())
Expand Down Expand Up @@ -824,6 +826,40 @@ impl Object {
Ok(JsValue::new(false))
}
}

/// `Object.getOwnPropertyNames( object )`
///
/// More information:
/// - [ECMAScript reference][spec]
/// - [MDN documentation][mdn]
///
/// [spec]: https://tc39.es/ecma262/#sec-object.getownpropertynames
/// [mdn]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/getOwnPropertyNames
pub fn get_own_property_names(
_: &JsValue,
args: &[JsValue],
context: &mut Context,
) -> JsResult<JsValue> {
let o = args.get_or_undefined(0);
get_own_property_keys(o, GetOwnPropertyKeysType::String, context)
}

/// `Object.getOwnPropertySymbols( object )`
///
/// More information:
/// - [ECMAScript reference][spec]
/// - [MDN documentation][mdn]
///
/// [spec]: https://tc39.es/ecma262/#sec-object.getownpropertysymbols
/// [mdn]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/getOwnPropertySymbols
pub fn get_own_property_symbols(
_: &JsValue,
args: &[JsValue],
context: &mut Context,
) -> JsResult<JsValue> {
let o = args.get_or_undefined(0);
get_own_property_keys(o, GetOwnPropertyKeysType::Symbol, context)
}
kevinputera marked this conversation as resolved.
Show resolved Hide resolved
}

/// The abstract operation ObjectDefineProperties
Expand Down Expand Up @@ -877,3 +913,48 @@ fn object_define_properties(
// 7. Return O.
Ok(())
}

/// Type enum used in the abstract operation GetOwnPropertyKeys
#[derive(Debug, Copy, Clone)]
enum GetOwnPropertyKeysType {
kevinputera marked this conversation as resolved.
Show resolved Hide resolved
String,
Symbol,
}

/// The abstract operation GetOwnPropertyKeys
///
/// More information:
/// - [ECMAScript reference][spec]
///
/// [spec]: https://tc39.es/ecma262/#sec-getownpropertykeys
fn get_own_property_keys(
o: &JsValue,
r#type: GetOwnPropertyKeysType,
context: &mut Context,
) -> JsResult<JsValue> {
// 1. Let obj be ? ToObject(o).
let obj = o.to_object(context)?;

// 2. Let keys be ? obj.[[OwnPropertyKeys]]().
let keys = obj.__own_property_keys__(context)?;

// 3. Let nameList be a new empty List.
// 4. For each element nextKey of keys, do
let name_list: Vec<_> = keys
.iter()
kevinputera marked this conversation as resolved.
Show resolved Hide resolved
.filter_map(|next_key| {
// a. If Type(nextKey) is Symbol and type is symbol or Type(nextKey) is String and type is string, then
// i. Append nextKey as the last element of nameList.
use GetOwnPropertyKeysType as Type;
match (r#type, next_key) {
(Type::String, PropertyKey::String(key)) => Some(key.clone().into()),
(Type::String, PropertyKey::Index(index)) => Some(index.to_string().into()),
jedel1043 marked this conversation as resolved.
Show resolved Hide resolved
(Type::Symbol, PropertyKey::Symbol(symbol)) => Some(symbol.clone().into()),
_ => None,
}
})
.collect();
kevinputera marked this conversation as resolved.
Show resolved Hide resolved

// 5. Return CreateArrayFromList(nameList).
Ok(Array::create_array_from_list(name_list, context).into())
}