diff --git a/nova_vm/src/ecmascript/builtins/indexed_collections/typed_array_objects/abstract_operations.rs b/nova_vm/src/ecmascript/builtins/indexed_collections/typed_array_objects/abstract_operations.rs index b43b43d2..40bc2b21 100644 --- a/nova_vm/src/ecmascript/builtins/indexed_collections/typed_array_objects/abstract_operations.rs +++ b/nova_vm/src/ecmascript/builtins/indexed_collections/typed_array_objects/abstract_operations.rs @@ -10,6 +10,7 @@ use crate::{ get_value_from_buffer, is_detached_buffer, is_fixed_length_array_buffer, set_value_in_buffer, Ordering, ViewedArrayBufferByteLength, }, + indexed_collections::typed_array_objects::typed_array_intrinsic_object::require_internal_slot_typed_array, ordinary::get_prototype_from_constructor, typed_array::{ data::{TypedArrayArrayLength, TypedArrayHeapData}, @@ -19,8 +20,8 @@ use crate::{ }, execution::{agent::ExceptionType, Agent, JsResult, ProtoIntrinsics}, types::{ - Function, InternalMethods, InternalSlots, IntoFunction, Object, PropertyKey, Value, - Viewable, + Function, InternalMethods, InternalSlots, IntoFunction, Object, PropertyKey, U8Clamped, + Value, Viewable, }, }, engine::context::GcScope, @@ -29,8 +30,8 @@ use crate::{ }; pub(crate) struct TypedArrayWithBufferWitnessRecords { - object: TypedArray, - cached_buffer_byte_length: Option, + pub object: TypedArray, + pub cached_buffer_byte_length: Option, } /// ### [10.4.5.9 MakeTypedArrayWithBufferWitnessRecord ( obj, order )](https://tc39.es/ecma262/#sec-maketypedarraywithbufferwitnessrecord) @@ -232,6 +233,48 @@ pub(crate) fn is_typed_array_out_of_bounds( false } +/// ### [23.2.4.4 ValidateTypedArray ( O, order )](https://tc39.es/ecma262/#sec-validatetypedarray) +/// +/// The abstract operation ValidateTypedArray takes arguments O (an ECMAScript +/// language value) and order (seq-cst or unordered) and returns either a normal +/// completion containing a TypedArray With Buffer Witness Record or a throw +/// completion. +pub(crate) fn validate_typed_array( + agent: &mut Agent, + o: Value, + order: Ordering, +) -> JsResult { + // 1. Perform ? RequireInternalSlot(O, [[TypedArrayName]]). + let o = require_internal_slot_typed_array(agent, o)?; + // 2. Assert: O has a [[ViewedArrayBuffer]] internal slot. + // 3. Let taRecord be MakeTypedArrayWithBufferWitnessRecord(O, order). + let ta_record = make_typed_array_with_buffer_witness_record(agent, o, order); + // 4. If IsTypedArrayOutOfBounds(taRecord) is true, throw a TypeError exception. + if match o { + TypedArray::Int8Array(_) => is_typed_array_out_of_bounds::(agent, &ta_record), + TypedArray::Uint8Array(_) => is_typed_array_out_of_bounds::(agent, &ta_record), + TypedArray::Uint8ClampedArray(_) => { + is_typed_array_out_of_bounds::(agent, &ta_record) + } + TypedArray::Int16Array(_) => is_typed_array_out_of_bounds::(agent, &ta_record), + TypedArray::Uint16Array(_) => is_typed_array_out_of_bounds::(agent, &ta_record), + TypedArray::Int32Array(_) => is_typed_array_out_of_bounds::(agent, &ta_record), + TypedArray::Uint32Array(_) => is_typed_array_out_of_bounds::(agent, &ta_record), + TypedArray::BigInt64Array(_) => is_typed_array_out_of_bounds::(agent, &ta_record), + TypedArray::BigUint64Array(_) => is_typed_array_out_of_bounds::(agent, &ta_record), + TypedArray::Float32Array(_) => is_typed_array_out_of_bounds::(agent, &ta_record), + TypedArray::Float64Array(_) => is_typed_array_out_of_bounds::(agent, &ta_record), + } { + return Err(agent.throw_exception_with_static_message( + ExceptionType::TypeError, + "TypedArray out of bounds", + )); + } + + // 5. Return taRecord. + Ok(ta_record) +} + /// ### [23.2.5.1.1 AllocateTypedArray ( constructorName, newTarget, defaultProto \[ , length \] )](https://tc39.es/ecma262/#sec-allocatetypedarray) /// /// The abstract operation AllocateTypedArray takes arguments constructorName diff --git a/nova_vm/src/ecmascript/builtins/indexed_collections/typed_array_objects/typed_array_intrinsic_object.rs b/nova_vm/src/ecmascript/builtins/indexed_collections/typed_array_objects/typed_array_intrinsic_object.rs index d88afcfe..20fb67fe 100644 --- a/nova_vm/src/ecmascript/builtins/indexed_collections/typed_array_objects/typed_array_intrinsic_object.rs +++ b/nova_vm/src/ecmascript/builtins/indexed_collections/typed_array_objects/typed_array_intrinsic_object.rs @@ -6,6 +6,8 @@ use crate::ecmascript::abstract_operations::testing_and_comparison::is_array; use crate::ecmascript::builders::builtin_function_builder::BuiltinFunctionBuilder; use crate::ecmascript::builders::ordinary_object_builder::OrdinaryObjectBuilder; use crate::ecmascript::builtins::array_buffer::Ordering; +use crate::ecmascript::builtins::indexed_collections::array_objects::array_iterator_objects::array_iterator::ArrayIterator; +use crate::ecmascript::builtins::indexed_collections::array_objects::array_iterator_objects::array_iterator::CollectionIteratorKind; use crate::ecmascript::builtins::typed_array::TypedArray; use crate::ecmascript::builtins::ArgumentsList; use crate::ecmascript::builtins::Behaviour; @@ -33,6 +35,8 @@ use crate::heap::WellKnownSymbolIndexes; use super::abstract_operations::is_typed_array_out_of_bounds; use super::abstract_operations::make_typed_array_with_buffer_witness_record; use super::abstract_operations::typed_array_byte_length; +use super::abstract_operations::typed_array_length; +use super::abstract_operations::validate_typed_array; pub struct TypedArrayIntrinsicObject; @@ -487,14 +491,24 @@ impl TypedArrayPrototype { todo!() } + /// ### [23.2.3.7 %TypedArray%.prototype.entries ( )](https://tc39.es/ecma262/#sec-%typedarray%.prototype.entries) fn entries( - _agent: &mut Agent, + agent: &mut Agent, _gc: GcScope<'_, '_>, - _this_value: Value, + this_value: Value, _: ArgumentsList, ) -> JsResult { - todo!() + // 1. Let O be the this value. + // 2. Perform ? ValidateTypedArray(O, seq-cst). + let o = validate_typed_array(agent, this_value, Ordering::SeqCst)?; + // 3. Return CreateArrayIterator(O, key+value). + Ok(ArrayIterator::from_object( + agent, + o.object.into_object(), + CollectionIteratorKind::KeyAndValue, + ) + .into_value()) } fn every( @@ -607,14 +621,22 @@ impl TypedArrayPrototype { todo!() } + /// ### [23.2.3.19 %TypedArray%.prototype.keys ( )](https://tc39.es/ecma262/#sec-%typedarray%.prototype.keys) fn keys( - _agent: &mut Agent, + agent: &mut Agent, _gc: GcScope<'_, '_>, - _this_value: Value, + this_value: Value, _: ArgumentsList, ) -> JsResult { - todo!() + // 1. Let O be the this value. + // 2. Perform ? ValidateTypedArray(O, seq-cst). + let o = validate_typed_array(agent, this_value, Ordering::SeqCst)?; + // 3. Return CreateArrayIterator(O, key). + Ok( + ArrayIterator::from_object(agent, o.object.into_object(), CollectionIteratorKind::Key) + .into_value(), + ) } fn last_index_of( @@ -627,14 +649,54 @@ impl TypedArrayPrototype { todo!() } + /// ### [23.2.3.21 get %TypedArray%.prototype.length](https://tc39.es/ecma262/#sec-get-%typedarray%.prototype.length) fn get_length( - _agent: &mut Agent, + agent: &mut Agent, _gc: GcScope<'_, '_>, - _this_value: Value, + this_value: Value, _: ArgumentsList, ) -> JsResult { - todo!() + // 1. Let O be the this value. + // 2. Perform ? RequireInternalSlot(O, [[TypedArrayName]]). + // 3. Assert: O has [[ViewedArrayBuffer]] and [[ArrayLength]] internal slots. + let o = require_internal_slot_typed_array(agent, this_value)?; + // 4. Let taRecord be MakeTypedArrayWithBufferWitnessRecord(O, seq-cst). + let ta_record = make_typed_array_with_buffer_witness_record(agent, o, Ordering::SeqCst); + // 5. If IsTypedArrayOutOfBounds(taRecord) is true, return +0𝔽. + if match o { + TypedArray::Int8Array(_) => is_typed_array_out_of_bounds::(agent, &ta_record), + TypedArray::Uint8Array(_) => is_typed_array_out_of_bounds::(agent, &ta_record), + TypedArray::Uint8ClampedArray(_) => { + is_typed_array_out_of_bounds::(agent, &ta_record) + } + TypedArray::Int16Array(_) => is_typed_array_out_of_bounds::(agent, &ta_record), + TypedArray::Uint16Array(_) => is_typed_array_out_of_bounds::(agent, &ta_record), + TypedArray::Int32Array(_) => is_typed_array_out_of_bounds::(agent, &ta_record), + TypedArray::Uint32Array(_) => is_typed_array_out_of_bounds::(agent, &ta_record), + TypedArray::BigInt64Array(_) => is_typed_array_out_of_bounds::(agent, &ta_record), + TypedArray::BigUint64Array(_) => is_typed_array_out_of_bounds::(agent, &ta_record), + TypedArray::Float32Array(_) => is_typed_array_out_of_bounds::(agent, &ta_record), + TypedArray::Float64Array(_) => is_typed_array_out_of_bounds::(agent, &ta_record), + } { + return Ok(Value::pos_zero()); + } + // 6. Let length be TypedArrayLength(taRecord). + let length = match o { + TypedArray::Int8Array(_) => typed_array_length::(agent, &ta_record), + TypedArray::Uint8Array(_) => typed_array_length::(agent, &ta_record), + TypedArray::Uint8ClampedArray(_) => typed_array_length::(agent, &ta_record), + TypedArray::Int16Array(_) => typed_array_length::(agent, &ta_record), + TypedArray::Uint16Array(_) => typed_array_length::(agent, &ta_record), + TypedArray::Int32Array(_) => typed_array_length::(agent, &ta_record), + TypedArray::Uint32Array(_) => typed_array_length::(agent, &ta_record), + TypedArray::BigInt64Array(_) => typed_array_length::(agent, &ta_record), + TypedArray::BigUint64Array(_) => typed_array_length::(agent, &ta_record), + TypedArray::Float32Array(_) => typed_array_length::(agent, &ta_record), + TypedArray::Float64Array(_) => typed_array_length::(agent, &ta_record), + } as i64; + // 7. Return 𝔽(length). + Ok(Value::try_from(length).unwrap()) } fn map( @@ -767,14 +829,26 @@ impl TypedArrayPrototype { todo!(); } + /// ### [23.2.3.35 %TypedArray%.prototype.values ( )](https://tc39.es/ecma262/#sec-get-%typedarray%.prototype-%symbol.tostringtag%) fn values( - _agent: &mut Agent, + agent: &mut Agent, _gc: GcScope<'_, '_>, - _this_value: Value, + this_value: Value, _: ArgumentsList, ) -> JsResult { - todo!(); + // 1. Let O be the this value. + // 2. Perform ? ValidateTypedArray(O, seq-cst). + let o = validate_typed_array(agent, this_value, Ordering::SeqCst)?; + // 3. Return CreateArrayIterator(O, value). + Ok( + ArrayIterator::from_object( + agent, + o.object.into_object(), + CollectionIteratorKind::Value, + ) + .into_value(), + ) } fn with( @@ -787,14 +861,39 @@ impl TypedArrayPrototype { todo!(); } + /// ### [23.2.3.38 get %TypedArray%.prototype \[ %Symbol.toStringTag% \]](https://tc39.es/ecma262/#sec-get-%typedarray%.prototype-%symbol.tostringtag%) fn get_to_string_tag( _agent: &mut Agent, _gc: GcScope<'_, '_>, - _this_value: Value, + this_value: Value, _: ArgumentsList, ) -> JsResult { - todo!(); + // 1. Let O be the this value. + if let Ok(o) = TypedArray::try_from(this_value) { + // 4. Let name be O.[[TypedArrayName]]. + // 5. Assert: name is a String. + // 6. Return name. + match o { + TypedArray::Int8Array(_) => Ok(BUILTIN_STRING_MEMORY.Int8Array.into()), + TypedArray::Uint8Array(_) => Ok(BUILTIN_STRING_MEMORY.Uint8Array.into()), + TypedArray::Uint8ClampedArray(_) => { + Ok(BUILTIN_STRING_MEMORY.Uint8ClampedArray.into()) + } + TypedArray::Int16Array(_) => Ok(BUILTIN_STRING_MEMORY.Int16Array.into()), + TypedArray::Uint16Array(_) => Ok(BUILTIN_STRING_MEMORY.Uint16Array.into()), + TypedArray::Int32Array(_) => Ok(BUILTIN_STRING_MEMORY.Int32Array.into()), + TypedArray::Uint32Array(_) => Ok(BUILTIN_STRING_MEMORY.Uint32Array.into()), + TypedArray::BigInt64Array(_) => Ok(BUILTIN_STRING_MEMORY.BigInt64Array.into()), + TypedArray::BigUint64Array(_) => Ok(BUILTIN_STRING_MEMORY.BigUint64Array.into()), + TypedArray::Float32Array(_) => Ok(BUILTIN_STRING_MEMORY.Float32Array.into()), + TypedArray::Float64Array(_) => Ok(BUILTIN_STRING_MEMORY.Float64Array.into()), + } + } else { + // 2. If O is not an Object, return undefined. + // 3. If O does not have a [[TypedArrayName]] internal slot, return undefined. + Ok(Value::Undefined) + } } pub(crate) fn create_intrinsic(agent: &mut Agent, realm: RealmIdentifier) { diff --git a/tests/expectations.json b/tests/expectations.json index e1bb81c0..fb1a7384 100644 --- a/tests/expectations.json +++ b/tests/expectations.json @@ -109,7 +109,6 @@ "built-ins/Array/proto-from-ctor-realm-two.js": "FAIL", "built-ins/Array/proto-from-ctor-realm-zero.js": "FAIL", "built-ins/Array/prototype/Symbol.unscopables/prop-desc.js": "FAIL", - "built-ins/Array/prototype/at/coerced-index-resize.js": "CRASH", "built-ins/Array/prototype/at/typed-array-resizable-buffer.js": "CRASH", "built-ins/Array/prototype/concat/Array.prototype.concat_large-typed-array.js": "CRASH", "built-ins/Array/prototype/concat/Array.prototype.concat_small-typed-array.js": "CRASH", @@ -9912,17 +9911,9 @@ "built-ins/TypedArray/out-of-bounds-get-and-set.js": "CRASH", "built-ins/TypedArray/out-of-bounds-has.js": "CRASH", "built-ins/TypedArray/prototype/Symbol.toStringTag/BigInt/detached-buffer.js": "CRASH", - "built-ins/TypedArray/prototype/Symbol.toStringTag/BigInt/invoked-as-accessor.js": "CRASH", - "built-ins/TypedArray/prototype/Symbol.toStringTag/BigInt/invoked-as-func.js": "CRASH", "built-ins/TypedArray/prototype/Symbol.toStringTag/BigInt/return-typedarrayname.js": "CRASH", - "built-ins/TypedArray/prototype/Symbol.toStringTag/BigInt/this-has-no-typedarrayname-internal.js": "CRASH", - "built-ins/TypedArray/prototype/Symbol.toStringTag/BigInt/this-is-not-object.js": "CRASH", "built-ins/TypedArray/prototype/Symbol.toStringTag/detached-buffer.js": "CRASH", - "built-ins/TypedArray/prototype/Symbol.toStringTag/invoked-as-accessor.js": "CRASH", - "built-ins/TypedArray/prototype/Symbol.toStringTag/invoked-as-func.js": "CRASH", "built-ins/TypedArray/prototype/Symbol.toStringTag/return-typedarrayname.js": "CRASH", - "built-ins/TypedArray/prototype/Symbol.toStringTag/this-has-no-typedarrayname-internal.js": "CRASH", - "built-ins/TypedArray/prototype/Symbol.toStringTag/this-is-not-object.js": "CRASH", "built-ins/TypedArray/prototype/at/BigInt/return-abrupt-from-this-out-of-bounds.js": "CRASH", "built-ins/TypedArray/prototype/at/coerced-index-resize.js": "CRASH", "built-ins/TypedArray/prototype/at/index-argument-tointeger.js": "CRASH", @@ -10014,16 +10005,12 @@ "built-ins/TypedArray/prototype/entries/BigInt/return-abrupt-from-this-out-of-bounds.js": "CRASH", "built-ins/TypedArray/prototype/entries/BigInt/return-itor.js": "CRASH", "built-ins/TypedArray/prototype/entries/detached-buffer.js": "CRASH", - "built-ins/TypedArray/prototype/entries/invoked-as-func.js": "CRASH", - "built-ins/TypedArray/prototype/entries/invoked-as-method.js": "CRASH", "built-ins/TypedArray/prototype/entries/iter-prototype.js": "CRASH", "built-ins/TypedArray/prototype/entries/resizable-buffer-grow-mid-iteration.js": "CRASH", "built-ins/TypedArray/prototype/entries/resizable-buffer-shrink-mid-iteration.js": "CRASH", "built-ins/TypedArray/prototype/entries/resizable-buffer.js": "CRASH", "built-ins/TypedArray/prototype/entries/return-abrupt-from-this-out-of-bounds.js": "CRASH", "built-ins/TypedArray/prototype/entries/return-itor.js": "CRASH", - "built-ins/TypedArray/prototype/entries/this-is-not-object.js": "CRASH", - "built-ins/TypedArray/prototype/entries/this-is-not-typedarray-instance.js": "CRASH", "built-ins/TypedArray/prototype/every/BigInt/callbackfn-arguments-with-thisarg.js": "CRASH", "built-ins/TypedArray/prototype/every/BigInt/callbackfn-arguments-without-thisarg.js": "CRASH", "built-ins/TypedArray/prototype/every/BigInt/callbackfn-detachbuffer.js": "CRASH", @@ -10434,16 +10421,12 @@ "built-ins/TypedArray/prototype/keys/BigInt/return-abrupt-from-this-out-of-bounds.js": "CRASH", "built-ins/TypedArray/prototype/keys/BigInt/return-itor.js": "CRASH", "built-ins/TypedArray/prototype/keys/detached-buffer.js": "CRASH", - "built-ins/TypedArray/prototype/keys/invoked-as-func.js": "CRASH", - "built-ins/TypedArray/prototype/keys/invoked-as-method.js": "CRASH", "built-ins/TypedArray/prototype/keys/iter-prototype.js": "CRASH", "built-ins/TypedArray/prototype/keys/resizable-buffer-grow-mid-iteration.js": "CRASH", "built-ins/TypedArray/prototype/keys/resizable-buffer-shrink-mid-iteration.js": "CRASH", "built-ins/TypedArray/prototype/keys/resizable-buffer.js": "CRASH", "built-ins/TypedArray/prototype/keys/return-abrupt-from-this-out-of-bounds.js": "CRASH", "built-ins/TypedArray/prototype/keys/return-itor.js": "CRASH", - "built-ins/TypedArray/prototype/keys/this-is-not-object.js": "CRASH", - "built-ins/TypedArray/prototype/keys/this-is-not-typedarray-instance.js": "CRASH", "built-ins/TypedArray/prototype/lastIndexOf/BigInt/detached-buffer-during-fromIndex-returns-minus-one-for-undefined.js": "CRASH", "built-ins/TypedArray/prototype/lastIndexOf/BigInt/detached-buffer-during-fromIndex-returns-minus-one-for-zero.js": "CRASH", "built-ins/TypedArray/prototype/lastIndexOf/BigInt/detached-buffer.js": "CRASH", @@ -10484,16 +10467,12 @@ "built-ins/TypedArray/prototype/length/BigInt/resizable-array-buffer-fixed.js": "CRASH", "built-ins/TypedArray/prototype/length/BigInt/return-length.js": "CRASH", "built-ins/TypedArray/prototype/length/detached-buffer.js": "CRASH", - "built-ins/TypedArray/prototype/length/invoked-as-accessor.js": "CRASH", - "built-ins/TypedArray/prototype/length/invoked-as-func.js": "CRASH", "built-ins/TypedArray/prototype/length/resizable-array-buffer-auto.js": "CRASH", "built-ins/TypedArray/prototype/length/resizable-array-buffer-fixed.js": "CRASH", "built-ins/TypedArray/prototype/length/resizable-buffer-assorted.js": "CRASH", "built-ins/TypedArray/prototype/length/resized-out-of-bounds-1.js": "CRASH", "built-ins/TypedArray/prototype/length/resized-out-of-bounds-2.js": "CRASH", "built-ins/TypedArray/prototype/length/return-length.js": "CRASH", - "built-ins/TypedArray/prototype/length/this-has-no-typedarrayname-internal.js": "CRASH", - "built-ins/TypedArray/prototype/length/this-is-not-object.js": "CRASH", "built-ins/TypedArray/prototype/map/BigInt/arraylength-internal.js": "CRASH", "built-ins/TypedArray/prototype/map/BigInt/callbackfn-arguments-with-thisarg.js": "CRASH", "built-ins/TypedArray/prototype/map/BigInt/callbackfn-arguments-without-thisarg.js": "CRASH", @@ -10988,8 +10967,6 @@ "built-ins/TypedArray/prototype/values/BigInt/return-abrupt-from-this-out-of-bounds.js": "CRASH", "built-ins/TypedArray/prototype/values/BigInt/return-itor.js": "CRASH", "built-ins/TypedArray/prototype/values/detached-buffer.js": "CRASH", - "built-ins/TypedArray/prototype/values/invoked-as-func.js": "CRASH", - "built-ins/TypedArray/prototype/values/invoked-as-method.js": "CRASH", "built-ins/TypedArray/prototype/values/iter-prototype.js": "CRASH", "built-ins/TypedArray/prototype/values/make-in-bounds-after-exhausted.js": "CRASH", "built-ins/TypedArray/prototype/values/make-out-of-bounds-after-exhausted.js": "CRASH", @@ -10998,8 +10975,6 @@ "built-ins/TypedArray/prototype/values/resizable-buffer.js": "CRASH", "built-ins/TypedArray/prototype/values/return-abrupt-from-this-out-of-bounds.js": "CRASH", "built-ins/TypedArray/prototype/values/return-itor.js": "CRASH", - "built-ins/TypedArray/prototype/values/this-is-not-object.js": "CRASH", - "built-ins/TypedArray/prototype/values/this-is-not-typedarray-instance.js": "CRASH", "built-ins/TypedArray/prototype/with/BigInt/early-type-coercion-bigint.js": "CRASH", "built-ins/TypedArray/prototype/with/early-type-coercion.js": "CRASH", "built-ins/TypedArray/prototype/with/ignores-species.js": "CRASH", @@ -21104,7 +21079,6 @@ "language/statements/class/subclass/builtin-objects/RegExp/lastIndex.js": "CRASH", "language/statements/class/subclass/builtin-objects/RegExp/regular-subclassing.js": "CRASH", "language/statements/class/subclass/builtin-objects/RegExp/super-must-be-called.js": "CRASH", - "language/statements/class/subclass/builtin-objects/TypedArray/regular-subclassing.js": "CRASH", "language/statements/class/subclass/builtin-objects/WeakMap/regular-subclassing.js": "CRASH", "language/statements/class/subclass/builtin-objects/WeakMap/super-must-be-called.js": "CRASH", "language/statements/class/subclass/builtin-objects/WeakSet/regular-subclassing.js": "CRASH", diff --git a/tests/metrics.json b/tests/metrics.json index dddfab69..2b0b3c87 100644 --- a/tests/metrics.json +++ b/tests/metrics.json @@ -1,9 +1,9 @@ { "results": { - "crash": 13925, - "fail": 9700, - "pass": 21621, - "skip": 42, + "crash": 13897, + "fail": 9702, + "pass": 21643, + "skip": 46, "timeout": 3, "unresolved": 0 },