Skip to content

Commit

Permalink
Move CopyDataProperties from Value to GcObject
Browse files Browse the repository at this point in the history
  • Loading branch information
raskad committed Aug 1, 2021
1 parent 72d4eab commit 96437ee
Show file tree
Hide file tree
Showing 3 changed files with 69 additions and 65 deletions.
67 changes: 67 additions & 0 deletions boa/src/object/gcobject.rs
Original file line number Diff line number Diff line change
Expand Up @@ -914,6 +914,73 @@ impl GcObject {
context.throw_type_error("property 'constructor' is not a constructor")
}
}

/// `7.3.25 CopyDataProperties ( target, source, excludedItems )`
///
/// More information:
/// - [ECMAScript][spec]
///
/// [spec]: https://tc39.es/ecma262/#sec-copydataproperties
#[inline]
pub fn copy_data_properties<K>(
&mut self,
source: &Value,
excluded_keys: Vec<K>,
context: &mut Context,
) -> Result<()>
where
K: Into<PropertyKey>,
{
// 1. Assert: Type(target) is Object.
// 2. Assert: excludedItems is a List of property keys.
// 3. If source is undefined or null, return target.
if source.is_null_or_undefined() {
return Ok(());
}

// 4. Let from be ! ToObject(source).
let from = source.to_object(context)?;

// 5. Let keys be ? from.[[OwnPropertyKeys]]().
// 6. For each element nextKey of keys, do
let excluded_keys: Vec<PropertyKey> = excluded_keys.into_iter().map(|e| e.into()).collect();
for key in from.own_property_keys() {
// a. Let excluded be false.
let mut excluded = false;

// b. For each element e of excludedItems, do
for e in &excluded_keys {
// i. If SameValue(e, nextKey) is true, then
if *e == key {
// 1. Set excluded to true.
excluded = true
}
}
// c. If excluded is false, then
if !excluded {
// i. Let desc be ? from.[[GetOwnProperty]](nextKey).
let desc = from.get_own_property(&key);

// ii. If desc is not undefined and desc.[[Enumerable]] is true, then
if let Some(desc) = desc {
if desc.enumerable() {
// 1. Let propValue be ? Get(from, nextKey).
let prop_value = from.get(&key, from.clone().into(), context)?;

// 2. Perform ! CreateDataPropertyOrThrow(target, nextKey, propValue).
self.define_property_or_throw(
key,
DataDescriptor::new(prop_value, Attribute::all()),
context,
)?;
}
}
}
}

// 7. Return target.
Ok(())
}
}

impl AsRef<GcCell<Object>> for GcObject {
Expand Down
4 changes: 2 additions & 2 deletions boa/src/syntax/ast/node/declaration/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -461,14 +461,14 @@ impl DeclarationPatternObject {
// 1. Let lhs be ? ResolveBinding(StringValue of BindingIdentifier, environment).

// 2. Let restObj be ! OrdinaryObjectCreate(%Object.prototype%).
let rest_obj = Value::new_object(context);
let mut rest_obj = context.construct_object();

// 3. Perform ? CopyDataProperties(restObj, value, excludedNames).
rest_obj.copy_data_properties(&value, excluded_keys.clone(), context)?;

// 4. If environment is undefined, return PutValue(lhs, restObj).
// 5. Return InitializeReferencedBinding(lhs, restObj).
results.push((property_name.clone(), rest_obj));
results.push((property_name.clone(), rest_obj.into()));
}
// BindingElement : BindingPattern Initializer[opt]
BindingPattern {
Expand Down
63 changes: 0 additions & 63 deletions boa/src/value/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -549,69 +549,6 @@ impl Value {
}
}

/// `7.3.25 CopyDataProperties ( target, source, excludedItems )`
///
/// More information:
/// - [ECMAScript][spec]
///
/// [spec]: https://tc39.es/ecma262/#sec-copydataproperties
#[inline]
pub fn copy_data_properties<K>(
&self,
source: &Value,
excluded_keys: Vec<K>,
context: &mut Context,
) -> Result<()>
where
K: Into<PropertyKey>,
{
// 1. Assert: Type(target) is Object.
// 2. Assert: excludedItems is a List of property keys.
// 3. If source is undefined or null, return target.
if source.is_null_or_undefined() {
return Ok(());
}

// 4. Let from be ! ToObject(source).
let from = source.to_object(context)?;

// 5. Let keys be ? from.[[OwnPropertyKeys]]().
// 6. For each element nextKey of keys, do
let excluded_keys: Vec<PropertyKey> = excluded_keys.into_iter().map(|e| e.into()).collect();
for key in from.own_property_keys() {
// a. Let excluded be false.
let mut excluded = false;

// b. For each element e of excludedItems, do
for e in &excluded_keys {
// i. If SameValue(e, nextKey) is true, then
if *e == key {
// 1. Set excluded to true.
excluded = true
}
}
// c. If excluded is false, then
if !excluded {
// i. Let desc be ? from.[[GetOwnProperty]](nextKey).
let desc = from.get_own_property(&key);

// ii. If desc is not undefined and desc.[[Enumerable]] is true, then
if let Some(desc) = desc {
if desc.enumerable() {
// 1. Let propValue be ? Get(from, nextKey).
let prop_value = from.get(&key, from.clone().into(), context)?;

// 2. Perform ! CreateDataPropertyOrThrow(target, nextKey, propValue).
self.set_property(key, DataDescriptor::new(prop_value, Attribute::all()));
}
}
}
}

// 7. Return target.
Ok(())
}

/// The abstract operation ToPrimitive takes an input argument and an optional argument PreferredType.
///
/// <https://tc39.es/ecma262/#sec-toprimitive>
Expand Down

0 comments on commit 96437ee

Please sign in to comment.