diff --git a/boa/src/object/gcobject.rs b/boa/src/object/gcobject.rs index a138d7e098d..d2385252d16 100644 --- a/boa/src/object/gcobject.rs +++ b/boa/src/object/gcobject.rs @@ -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( + &mut self, + source: &Value, + excluded_keys: Vec, + context: &mut Context, + ) -> Result<()> + where + K: Into, + { + // 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 = 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> for GcObject { diff --git a/boa/src/syntax/ast/node/declaration/mod.rs b/boa/src/syntax/ast/node/declaration/mod.rs index a60bc28a779..75cb2f401d6 100644 --- a/boa/src/syntax/ast/node/declaration/mod.rs +++ b/boa/src/syntax/ast/node/declaration/mod.rs @@ -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 { diff --git a/boa/src/value/mod.rs b/boa/src/value/mod.rs index 7b95f5f53de..d1e519e69d5 100644 --- a/boa/src/value/mod.rs +++ b/boa/src/value/mod.rs @@ -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( - &self, - source: &Value, - excluded_keys: Vec, - context: &mut Context, - ) -> Result<()> - where - K: Into, - { - // 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 = 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. /// ///