From ae10d40dc038f4d694fc9d83101fc877971cecfb Mon Sep 17 00:00:00 2001 From: raskad <32105367+raskad@users.noreply.github.com> Date: Wed, 17 Aug 2022 11:03:38 +0000 Subject: [PATCH] Fix `arguments` object iterator function (#2231) This Pull Request changes the following: - Create the `%Array.prototype.values%` function object once and use it in both the `Array` prototype and as the `@@iterator` value of `arguments` objects. This fixes a test where `arguments[Symbol.iterator]` and `[][Symbol.iterator]` would not be equal. --- boa_engine/src/builtins/array/mod.rs | 19 ++++++++++--------- boa_engine/src/builtins/function/arguments.rs | 7 ++++--- boa_engine/src/context/intrinsics.rs | 15 ++++++++++++++- 3 files changed, 28 insertions(+), 13 deletions(-) diff --git a/boa_engine/src/builtins/array/mod.rs b/boa_engine/src/builtins/array/mod.rs index 549ce87398..54f2280029 100644 --- a/boa_engine/src/builtins/array/mod.rs +++ b/boa_engine/src/builtins/array/mod.rs @@ -52,7 +52,7 @@ impl BuiltIn for Array { .constructor(false) .build(); - let values_function = Self::values_intrinsic(context); + let values_function = context.intrinsics().objects().array_prototype_values(); let unscopables_object = Self::unscopables_intrinsic(context); ConstructorBuilder::with_standard_constructor( @@ -2738,6 +2738,15 @@ impl Array { )) } + /// Creates an `Array.prototype.values( )` function object. + pub(crate) fn create_array_prototype_values(context: &mut Context) -> JsFunction { + FunctionBuilder::native(context, Self::values) + .name("values") + .length(0) + .constructor(false) + .build() + } + /// `Array.prototype.keys( )` /// /// The keys method returns an iterable that iterates over the indexes in the array. @@ -2840,14 +2849,6 @@ impl Array { } } - pub(crate) fn values_intrinsic(context: &mut Context) -> JsFunction { - FunctionBuilder::native(context, Self::values) - .name("values") - .length(0) - .constructor(false) - .build() - } - /// `Array.prototype [ @@unscopables ]` /// /// The initial value of the 'unscopables' data property is an ordinary object diff --git a/boa_engine/src/builtins/function/arguments.rs b/boa_engine/src/builtins/function/arguments.rs index cc28c657a3..ab1626a87c 100644 --- a/boa_engine/src/builtins/function/arguments.rs +++ b/boa_engine/src/builtins/function/arguments.rs @@ -1,5 +1,4 @@ use crate::{ - builtins::Array, environments::DeclarativeEnvironment, object::{JsObject, ObjectData}, property::PropertyDescriptor, @@ -111,10 +110,11 @@ impl Arguments { // 7. Perform ! DefinePropertyOrThrow(obj, @@iterator, PropertyDescriptor { // [[Value]]: %Array.prototype.values%, [[Writable]]: true, [[Enumerable]]: false, // [[Configurable]]: true }). + let values_function = context.intrinsics().objects().array_prototype_values(); obj.define_property_or_throw( symbol::WellKnownSymbols::iterator(), PropertyDescriptor::builder() - .value(Array::values_intrinsic(context)) + .value(values_function) .writable(true) .enumerable(false) .configurable(true), @@ -263,10 +263,11 @@ impl Arguments { // 20. Perform ! DefinePropertyOrThrow(obj, @@iterator, PropertyDescriptor { // [[Value]]: %Array.prototype.values%, [[Writable]]: true, [[Enumerable]]: false, // [[Configurable]]: true }). + let values_function = context.intrinsics().objects().array_prototype_values(); obj.define_property_or_throw( WellKnownSymbols::iterator(), PropertyDescriptor::builder() - .value(Array::values_intrinsic(context)) + .value(values_function) .writable(true) .enumerable(false) .configurable(true), diff --git a/boa_engine/src/context/intrinsics.rs b/boa_engine/src/context/intrinsics.rs index 719b40939d..e8d7dac720 100644 --- a/boa_engine/src/context/intrinsics.rs +++ b/boa_engine/src/context/intrinsics.rs @@ -1,5 +1,7 @@ use crate::{ - builtins::{error::r#type::create_throw_type_error, iterable::IteratorPrototypes}, + builtins::{ + array::Array, error::r#type::create_throw_type_error, iterable::IteratorPrototypes, + }, object::{JsObject, ObjectData}, property::PropertyDescriptorBuilder, Context, @@ -407,6 +409,10 @@ impl StandardConstructors { pub struct IntrinsicObjects { /// %ThrowTypeError% intrinsic object throw_type_error: JsObject, + + /// %Array.prototype.values% + array_prototype_values: JsObject, + /// Cached iterator prototypes. iterator_prototypes: IteratorPrototypes, } @@ -416,6 +422,7 @@ impl IntrinsicObjects { pub fn init(context: &mut Context) -> Self { Self { throw_type_error: create_throw_type_error(context), + array_prototype_values: Array::create_array_prototype_values(context).into(), iterator_prototypes: IteratorPrototypes::init(context), } } @@ -426,6 +433,12 @@ impl IntrinsicObjects { self.throw_type_error.clone() } + /// Get the `%Array.prototype.values%` intrinsic object. + #[inline] + pub fn array_prototype_values(&self) -> JsObject { + self.array_prototype_values.clone() + } + /// Get the cached iterator prototypes. #[inline] pub fn iterator_prototypes(&self) -> &IteratorPrototypes {