Browse Source

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.
pull/2246/head
raskad 2 years ago
parent
commit
ae10d40dc0
  1. 19
      boa_engine/src/builtins/array/mod.rs
  2. 7
      boa_engine/src/builtins/function/arguments.rs
  3. 15
      boa_engine/src/context/intrinsics.rs

19
boa_engine/src/builtins/array/mod.rs

@ -52,7 +52,7 @@ impl BuiltIn for Array {
.constructor(false) .constructor(false)
.build(); .build();
let values_function = Self::values_intrinsic(context); let values_function = context.intrinsics().objects().array_prototype_values();
let unscopables_object = Self::unscopables_intrinsic(context); let unscopables_object = Self::unscopables_intrinsic(context);
ConstructorBuilder::with_standard_constructor( 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( )` /// `Array.prototype.keys( )`
/// ///
/// The keys method returns an iterable that iterates over the indexes in the array. /// 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 ]` /// `Array.prototype [ @@unscopables ]`
/// ///
/// The initial value of the 'unscopables' data property is an ordinary object /// The initial value of the 'unscopables' data property is an ordinary object

7
boa_engine/src/builtins/function/arguments.rs

@ -1,5 +1,4 @@
use crate::{ use crate::{
builtins::Array,
environments::DeclarativeEnvironment, environments::DeclarativeEnvironment,
object::{JsObject, ObjectData}, object::{JsObject, ObjectData},
property::PropertyDescriptor, property::PropertyDescriptor,
@ -111,10 +110,11 @@ impl Arguments {
// 7. Perform ! DefinePropertyOrThrow(obj, @@iterator, PropertyDescriptor { // 7. Perform ! DefinePropertyOrThrow(obj, @@iterator, PropertyDescriptor {
// [[Value]]: %Array.prototype.values%, [[Writable]]: true, [[Enumerable]]: false, // [[Value]]: %Array.prototype.values%, [[Writable]]: true, [[Enumerable]]: false,
// [[Configurable]]: true }). // [[Configurable]]: true }).
let values_function = context.intrinsics().objects().array_prototype_values();
obj.define_property_or_throw( obj.define_property_or_throw(
symbol::WellKnownSymbols::iterator(), symbol::WellKnownSymbols::iterator(),
PropertyDescriptor::builder() PropertyDescriptor::builder()
.value(Array::values_intrinsic(context)) .value(values_function)
.writable(true) .writable(true)
.enumerable(false) .enumerable(false)
.configurable(true), .configurable(true),
@ -263,10 +263,11 @@ impl Arguments {
// 20. Perform ! DefinePropertyOrThrow(obj, @@iterator, PropertyDescriptor { // 20. Perform ! DefinePropertyOrThrow(obj, @@iterator, PropertyDescriptor {
// [[Value]]: %Array.prototype.values%, [[Writable]]: true, [[Enumerable]]: false, // [[Value]]: %Array.prototype.values%, [[Writable]]: true, [[Enumerable]]: false,
// [[Configurable]]: true }). // [[Configurable]]: true }).
let values_function = context.intrinsics().objects().array_prototype_values();
obj.define_property_or_throw( obj.define_property_or_throw(
WellKnownSymbols::iterator(), WellKnownSymbols::iterator(),
PropertyDescriptor::builder() PropertyDescriptor::builder()
.value(Array::values_intrinsic(context)) .value(values_function)
.writable(true) .writable(true)
.enumerable(false) .enumerable(false)
.configurable(true), .configurable(true),

15
boa_engine/src/context/intrinsics.rs

@ -1,5 +1,7 @@
use crate::{ 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}, object::{JsObject, ObjectData},
property::PropertyDescriptorBuilder, property::PropertyDescriptorBuilder,
Context, Context,
@ -407,6 +409,10 @@ impl StandardConstructors {
pub struct IntrinsicObjects { pub struct IntrinsicObjects {
/// %ThrowTypeError% intrinsic object /// %ThrowTypeError% intrinsic object
throw_type_error: JsObject, throw_type_error: JsObject,
/// %Array.prototype.values%
array_prototype_values: JsObject,
/// Cached iterator prototypes. /// Cached iterator prototypes.
iterator_prototypes: IteratorPrototypes, iterator_prototypes: IteratorPrototypes,
} }
@ -416,6 +422,7 @@ impl IntrinsicObjects {
pub fn init(context: &mut Context) -> Self { pub fn init(context: &mut Context) -> Self {
Self { Self {
throw_type_error: create_throw_type_error(context), throw_type_error: create_throw_type_error(context),
array_prototype_values: Array::create_array_prototype_values(context).into(),
iterator_prototypes: IteratorPrototypes::init(context), iterator_prototypes: IteratorPrototypes::init(context),
} }
} }
@ -426,6 +433,12 @@ impl IntrinsicObjects {
self.throw_type_error.clone() 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. /// Get the cached iterator prototypes.
#[inline] #[inline]
pub fn iterator_prototypes(&self) -> &IteratorPrototypes { pub fn iterator_prototypes(&self) -> &IteratorPrototypes {

Loading…
Cancel
Save