diff --git a/src/builtins/builtins-array-gen.cc b/src/builtins/builtins-array-gen.cc index 48eb954f83..ddcde0982e 100644 --- a/src/builtins/builtins-array-gen.cc +++ b/src/builtins/builtins-array-gen.cc @@ -45,13 +45,13 @@ void ArrayBuiltinsAssembler::TypedArrayMapResultGenerator() { // See tc39.github.io/ecma262/#sec-%typedarray%.prototype.map. TNode ArrayBuiltinsAssembler::TypedArrayMapProcessor( TNode k_value, TNode k) { - // 8. c. Let mapped_value be ? Call(callbackfn, T, « kValue, k, O »). + // 7c. Let mapped_value be ? Call(callbackfn, T, « kValue, k, O »). TNode k_number = ChangeUintPtrToTagged(k); TNode mapped_value = Call(context(), callbackfn(), this_arg(), k_value, k_number, o()); Label fast(this), slow(this), done(this), detached(this, Label::kDeferred); - // 8. d. Perform ? Set(A, Pk, mapped_value, true). + // 7d. Perform ? Set(A, Pk, mapped_value, true). // Since we know that A is a TypedArray, this always ends up in // #sec-integer-indexed-exotic-objects-set-p-v-receiver and then // tc39.github.io/ecma262/#sec-integerindexedelementset . @@ -59,9 +59,9 @@ TNode ArrayBuiltinsAssembler::TypedArrayMapProcessor( BIND(&fast); // #sec-integerindexedelementset - // 5. If arrayTypeName is "BigUint64Array" or "BigInt64Array", let + // 2. If arrayTypeName is "BigUint64Array" or "BigInt64Array", let // numValue be ? ToBigInt(v). - // 6. Otherwise, let numValue be ? ToNumber(value). + // 3. Otherwise, let numValue be ? ToNumber(value). TNode num_value; if (source_elements_kind_ == BIGINT64_ELEMENTS || source_elements_kind_ == BIGUINT64_ELEMENTS) { @@ -175,24 +175,15 @@ void ArrayBuiltinsAssembler::GenerateIteratingTypedArrayBuiltinBody( size_t i = 0; for (auto it = labels.begin(); it != labels.end(); ++i, ++it) { BIND(&*it); - Label done(this); source_elements_kind_ = static_cast(elements_kinds[i]); - // TODO(turbofan): Silently cancelling the loop on buffer detachment is a - // spec violation. Should go to &throw_detached and throw a TypeError - // instead. - VisitAllTypedArrayElements(array_buffer, processor, &done, direction, - typed_array); - Goto(&done); - // No exception, return success - BIND(&done); + VisitAllTypedArrayElements(array_buffer, processor, direction, typed_array); ReturnFromBuiltin(a_.value()); } } void ArrayBuiltinsAssembler::VisitAllTypedArrayElements( TNode array_buffer, const CallResultProcessor& processor, - Label* detached, ForEachDirection direction, - TNode typed_array) { + ForEachDirection direction, TNode typed_array) { VariableList list({&a_, &k_}, zone()); TNode start = UintPtrConstant(0); @@ -208,12 +199,28 @@ void ArrayBuiltinsAssembler::VisitAllTypedArrayElements( BuildFastLoop( list, start, end, [&](TNode index) { - GotoIf(IsDetachedBuffer(array_buffer), detached); - TNode data_ptr = LoadJSTypedArrayDataPtr(typed_array); - TNode value = LoadFixedTypedArrayElementAsTagged( - data_ptr, index, source_elements_kind_); - k_ = index; - a_ = processor(this, value, index); + TVARIABLE(Object, value); + Label detached(this, Label::kDeferred); + Label process(this); + GotoIf(IsDetachedBuffer(array_buffer), &detached); + { + TNode data_ptr = LoadJSTypedArrayDataPtr(typed_array); + value = LoadFixedTypedArrayElementAsTagged(data_ptr, index, + source_elements_kind_); + Goto(&process); + } + + BIND(&detached); + { + value = UndefinedConstant(); + Goto(&process); + } + + BIND(&process); + { + k_ = index; + a_ = processor(this, value.value(), index); + } }, incr, advance_mode); } diff --git a/src/builtins/builtins-array-gen.h b/src/builtins/builtins-array-gen.h index 96833d9dea..1f169632bf 100644 --- a/src/builtins/builtins-array-gen.h +++ b/src/builtins/builtins-array-gen.h @@ -104,7 +104,7 @@ class ArrayBuiltinsAssembler : public CodeStubAssembler { private: void VisitAllTypedArrayElements(TNode array_buffer, const CallResultProcessor& processor, - Label* detached, ForEachDirection direction, + ForEachDirection direction, TNode typed_array); TNode callbackfn_; diff --git a/src/builtins/typed-array-every.tq b/src/builtins/typed-array-every.tq index fdd4961dee..8c662bffb7 100644 --- a/src/builtins/typed-array-every.tq +++ b/src/builtins/typed-array-every.tq @@ -7,24 +7,43 @@ namespace typed_array { const kBuiltinNameEvery: constexpr string = '%TypedArray%.prototype.every'; +// https://tc39.github.io/ecma262/#sec-%typedarray%.prototype.every transitioning macro EveryAllElements(implicit context: Context)( array: typed_array::AttachedJSTypedArray, callbackfn: Callable, thisArg: JSAny): Boolean { let witness = typed_array::NewAttachedJSTypedArrayWitness(array); const length: uintptr = witness.Get().length; + + // 6. Repeat, while k < len for (let k: uintptr = 0; k < length; k++) { - // BUG(4895): We should throw on detached buffers rather than simply exit. - witness.Recheck() otherwise break; - const value: JSAny = witness.Load(k); + // 6a. Let Pk be ! ToString(𝔽(k)). + // There is no need to cast ToString to load elements. + + // 6b. Let kValue be ! Get(O, Pk). + // kValue must be undefined when the buffer is detached. + let value: JSAny; + try { + witness.Recheck() otherwise goto IsDetached; + value = witness.Load(k); + } label IsDetached deferred { + value = Undefined; + } + + // 6c. Let testResult be ! ToBoolean(? Call(callbackfn, thisArg, « kValue, + // 𝔽(k), O »)). // TODO(v8:4153): Consider versioning this loop for Smi and non-Smi // indices to optimize Convert(k) for the most common case. const result = Call( context, callbackfn, thisArg, value, Convert(k), witness.GetStable()); + // 6d. If testResult is false, return false. if (!ToBoolean(result)) { return False; } + // 6e. Set k to k + 1. (done by the loop). } + + // 7. Return true. return True; } diff --git a/src/builtins/typed-array-filter.tq b/src/builtins/typed-array-filter.tq index 15d40f92eb..18fbce9f09 100644 --- a/src/builtins/typed-array-filter.tq +++ b/src/builtins/typed-array-filter.tq @@ -38,11 +38,15 @@ transitioning javascript builtin TypedArrayPrototypeFilter( // 8. Let captured be 0. // 9. Repeat, while k < len for (let k: uintptr = 0; k < len; k++) { - witness.Recheck() otherwise IsDetached; - + let value: JSAny; // a. Let Pk be ! ToString(k). // b. Let kValue be ? Get(O, Pk). - const value: JSAny = witness.Load(k); + try { + witness.Recheck() otherwise goto IsDetached; + value = witness.Load(k); + } label IsDetached deferred { + value = Undefined; + } // c. Let selected be ToBoolean(? Call(callbackfn, T, « kValue, k, O // »)). @@ -57,7 +61,7 @@ transitioning javascript builtin TypedArrayPrototypeFilter( // ii. Increase captured by 1. if (ToBoolean(selected)) kept.Push(value); - // e.Increase k by 1. + // e. Increase k by 1. (done by the loop) } // 10. Let A be ? TypedArraySpeciesCreate(O, captured). diff --git a/src/builtins/typed-array-find.tq b/src/builtins/typed-array-find.tq index 24a13dbc23..b37b4ef8a9 100644 --- a/src/builtins/typed-array-find.tq +++ b/src/builtins/typed-array-find.tq @@ -7,24 +7,45 @@ namespace typed_array { const kBuiltinNameFind: constexpr string = '%TypedArray%.prototype.find'; +// https://tc39.github.io/ecma262/#sec-%typedarray%.prototype.find transitioning macro FindAllElements(implicit context: Context)( - array: typed_array::AttachedJSTypedArray, callbackfn: Callable, + array: typed_array::AttachedJSTypedArray, predicate: Callable, thisArg: JSAny): JSAny { let witness = typed_array::NewAttachedJSTypedArrayWitness(array); const length: uintptr = witness.Get().length; + + // 6. Repeat, while k < len for (let k: uintptr = 0; k < length; k++) { - // BUG(4895): We should throw on detached buffers rather than simply exit. - witness.Recheck() otherwise break; - const value: JSAny = witness.Load(k); + // 6a. Let Pk be ! ToString(𝔽(k)). + // There is no need to cast ToString to load elements. + + // 6b. Let kValue be ! Get(O, Pk). + // kValue must be undefined when the buffer is detached. + let value: JSAny; + try { + witness.Recheck() otherwise goto IsDetached; + value = witness.Load(k); + } label IsDetached deferred { + value = Undefined; + } + + // 6c. Let testResult be ! ToBoolean(? Call(predicate, thisArg, « kValue, + // 𝔽(k), O »)). // TODO(v8:4153): Consider versioning this loop for Smi and non-Smi // indices to optimize Convert(k) for the most common case. const result = Call( - context, callbackfn, thisArg, value, Convert(k), + context, predicate, thisArg, value, Convert(k), witness.GetStable()); + + // 6d. If testResult is true, return kValue. if (ToBoolean(result)) { return value; } + + // 6e. Set k to k + 1. (done by the loop). } + + // 7. Return undefined. return Undefined; } @@ -39,9 +60,9 @@ TypedArrayPrototypeFind( otherwise NotTypedArray; const uarray = typed_array::EnsureAttached(array) otherwise IsDetached; - const callbackfn = Cast(arguments[0]) otherwise NotCallable; + const predicate = Cast(arguments[0]) otherwise NotCallable; const thisArg = arguments[1]; - return FindAllElements(uarray, callbackfn, thisArg); + return FindAllElements(uarray, predicate, thisArg); } label NotCallable deferred { ThrowTypeError(MessageTemplate::kCalledNonCallable, arguments[0]); } label NotTypedArray deferred { diff --git a/src/builtins/typed-array-findindex.tq b/src/builtins/typed-array-findindex.tq index 7bb01151f3..aede90dc7f 100644 --- a/src/builtins/typed-array-findindex.tq +++ b/src/builtins/typed-array-findindex.tq @@ -9,19 +9,33 @@ const kBuiltinNameFindIndex: constexpr string = '%TypedArray%.prototype.findIndex'; transitioning macro FindIndexAllElements(implicit context: Context)( - array: typed_array::AttachedJSTypedArray, callbackfn: Callable, + array: typed_array::AttachedJSTypedArray, predicate: Callable, thisArg: JSAny): Number { let witness = typed_array::NewAttachedJSTypedArrayWitness(array); const length: uintptr = witness.Get().length; + + // 6. Repeat, while k < len for (let k: uintptr = 0; k < length; k++) { - // BUG(4895): We should throw on detached buffers rather than simply exit. - witness.Recheck() otherwise break; - const value: JSAny = witness.Load(k); + // 6a. Let Pk be ! ToString(𝔽(k)). + // There is no need to cast ToString to load elements. + + // 6b. Let kValue be ! Get(O, Pk). + // kValue must be undefined when the buffer is detached. + let value: JSAny; + try { + witness.Recheck() otherwise goto IsDetached; + value = witness.Load(k); + } label IsDetached deferred { + value = Undefined; + } + + // 6c. Let testResult be ! ToBoolean(? Call(predicate, thisArg, « kValue, + // 𝔽(k), O »)). // TODO(v8:4153): Consider versioning this loop for Smi and non-Smi // indices to optimize Convert(k) for the most common case. const indexNumber: Number = Convert(k); const result = Call( - context, callbackfn, thisArg, value, indexNumber, witness.GetStable()); + context, predicate, thisArg, value, indexNumber, witness.GetStable()); if (ToBoolean(result)) { return indexNumber; } @@ -40,9 +54,9 @@ TypedArrayPrototypeFindIndex( otherwise NotTypedArray; const uarray = typed_array::EnsureAttached(array) otherwise IsDetached; - const callbackfn = Cast(arguments[0]) otherwise NotCallable; + const predicate = Cast(arguments[0]) otherwise NotCallable; const thisArg = arguments[1]; - return FindIndexAllElements(uarray, callbackfn, thisArg); + return FindIndexAllElements(uarray, predicate, thisArg); } label NotCallable deferred { ThrowTypeError(MessageTemplate::kCalledNonCallable, arguments[0]); } label NotTypedArray deferred { diff --git a/src/builtins/typed-array-findlast.tq b/src/builtins/typed-array-findlast.tq index 634e17b936..15f67760c0 100644 --- a/src/builtins/typed-array-findlast.tq +++ b/src/builtins/typed-array-findlast.tq @@ -8,56 +8,28 @@ namespace typed_array { const kBuiltinNameFindLast: constexpr string = '%TypedArray%.prototype.findLast'; -// Continuation part of -// https://tc39.es/proposal-array-find-from-last/index.html#sec-%typedarray%.prototype.findlast -// when array buffer was detached. -transitioning builtin FindLastAllElementsDetachedContinuation( - implicit context: Context)( - array: JSTypedArray, predicate: Callable, thisArg: JSAny, - initialK: Number): JSAny { - // 6. Repeat, while k ≥ 0 - for (let k: Number = initialK; k >= 0; k--) { - // 6a. Let Pk be ! ToString(𝔽(k)). - // there is no need to cast ToString to load elements. - - // 6b. Let kValue be ! Get(O, Pk). - // kValue must be undefined when the buffer was detached. - - // 6c. Let testResult be ! ToBoolean(? Call(predicate, thisArg, « kValue, - // 𝔽(k), O »)). - // TODO(v8:4153): Consider versioning this loop for Smi and non-Smi - // indices to optimize Convert(k) for the most common case. - const result = - Call(context, predicate, thisArg, Undefined, Convert(k), array); - // 6d. If testResult is true, return kValue. - if (ToBoolean(result)) { - return Undefined; - } - - // 6e. Set k to k - 1. (done by the loop). - } - - // 7. Return undefined. - return Undefined; -} - // https://tc39.es/proposal-array-find-from-last/index.html#sec-%typedarray%.prototype.findlast transitioning macro FindLastAllElements(implicit context: Context)( array: typed_array::AttachedJSTypedArray, predicate: Callable, - thisArg: JSAny): JSAny labels -Bailout(Number) { + thisArg: JSAny): JSAny { let witness = typed_array::NewAttachedJSTypedArrayWitness(array); // 3. Let len be O.[[ArrayLength]]. const length: uintptr = witness.Get().length; // 5. Let k be len - 1. // 6. Repeat, while k ≥ 0 for (let k: uintptr = length; k-- > 0;) { - witness.Recheck() otherwise goto Bailout(Convert(k)); // 6a. Let Pk be ! ToString(𝔽(k)). - // there is no need to cast ToString to load elements. + // There is no need to cast ToString to load elements. // 6b. Let kValue be ! Get(O, Pk). - const value: JSAny = witness.Load(k); + // kValue must be undefined when the buffer was detached. + let value: JSAny; + try { + witness.Recheck() otherwise goto IsDetached; + value = witness.Load(k); + } label IsDetached deferred { + value = Undefined; + } // 6c. Let testResult be ! ToBoolean(? Call(predicate, thisArg, « kValue, // 𝔽(k), O »)). @@ -94,13 +66,7 @@ TypedArrayPrototypeFindLast( // 4. If IsCallable(predicate) is false, throw a TypeError exception. const predicate = Cast(arguments[0]) otherwise NotCallable; const thisArg = arguments[1]; - try { - return FindLastAllElements(uarray, predicate, thisArg) - otherwise Bailout; - } label Bailout(k: Number) deferred { - return FindLastAllElementsDetachedContinuation( - uarray, predicate, thisArg, k); - } + return FindLastAllElements(uarray, predicate, thisArg); } label NotCallable deferred { ThrowTypeError(MessageTemplate::kCalledNonCallable, arguments[0]); } label NotTypedArray deferred { diff --git a/src/builtins/typed-array-findlastindex.tq b/src/builtins/typed-array-findlastindex.tq index 4b20114c91..56d139d8b1 100644 --- a/src/builtins/typed-array-findlastindex.tq +++ b/src/builtins/typed-array-findlastindex.tq @@ -8,57 +8,28 @@ namespace typed_array { const kBuiltinNameFindLastIndex: constexpr string = '%TypedArray%.prototype.findIndexLast'; -// Continuation part of -// https://tc39.es/proposal-array-find-from-last/index.html#sec-%typedarray%.prototype.findlastindex -// when array buffer was detached. -transitioning builtin FindLastIndexAllElementsDetachedContinuation( - implicit context: Context)( - array: JSTypedArray, predicate: Callable, thisArg: JSAny, - initialK: Number): Number { - // 6. Repeat, while k ≥ 0 - for (let k: Number = initialK; k >= 0; k--) { - // 6a. Let Pk be ! ToString(𝔽(k)). - // there is no need to cast ToString to load elements. - - // 6b. Let kValue be ! Get(O, Pk). - // kValue must be undefined when the buffer was detached. - - // 6c. Let testResult be ! ToBoolean(? Call(predicate, thisArg, « kValue, - // 𝔽(k), O »)). - // TODO(v8:4153): Consider versioning this loop for Smi and non-Smi - // indices to optimize Convert(k) for the most common case. - const indexNumber: Number = Convert(k); - const result = - Call(context, predicate, thisArg, Undefined, indexNumber, array); - // 6d. If testResult is true, return 𝔽(k). - if (ToBoolean(result)) { - return indexNumber; - } - - // 6e. Set k to k - 1. (done by the loop). - } - - // 7. Return -1𝔽. - return -1; -} - // https://tc39.es/proposal-array-find-from-last/index.html#sec-%typedarray%.prototype.findlastindex transitioning macro FindLastIndexAllElements(implicit context: Context)( array: typed_array::AttachedJSTypedArray, predicate: Callable, - thisArg: JSAny): Number labels -Bailout(Number) { + thisArg: JSAny): Number { let witness = typed_array::NewAttachedJSTypedArrayWitness(array); // 3. Let len be O.[[ArrayLength]]. const length: uintptr = witness.Get().length; // 5. Let k be len - 1. // 6. Repeat, while k ≥ 0 for (let k: uintptr = length; k-- > 0;) { - witness.Recheck() otherwise goto Bailout(Convert(k)); // 6a. Let Pk be ! ToString(𝔽(k)). - // there is no need to cast ToString to load elements. + // There is no need to cast ToString to load elements. // 6b. Let kValue be ! Get(O, Pk). - const value: JSAny = witness.Load(k); + // kValue must be undefined when the buffer was detached. + let value: JSAny; + try { + witness.Recheck() otherwise goto IsDetached; + value = witness.Load(k); + } label IsDetached deferred { + value = Undefined; + } // 6c. Let testResult be ! ToBoolean(? Call(predicate, thisArg, « kValue, // 𝔽(k), O »)). @@ -96,13 +67,7 @@ TypedArrayPrototypeFindLastIndex( const predicate = Cast(arguments[0]) otherwise NotCallable; const thisArg = arguments[1]; - try { - return FindLastIndexAllElements(uarray, predicate, thisArg) - otherwise Bailout; - } label Bailout(k: Number) deferred { - return FindLastIndexAllElementsDetachedContinuation( - uarray, predicate, thisArg, k); - } + return FindLastIndexAllElements(uarray, predicate, thisArg); } label NotCallable deferred { ThrowTypeError(MessageTemplate::kCalledNonCallable, arguments[0]); } label NotTypedArray deferred { diff --git a/src/builtins/typed-array-foreach.tq b/src/builtins/typed-array-foreach.tq index d696d9c8dd..fa227bc75b 100644 --- a/src/builtins/typed-array-foreach.tq +++ b/src/builtins/typed-array-foreach.tq @@ -12,16 +12,33 @@ transitioning macro ForEachAllElements(implicit context: Context)( thisArg: JSAny): Undefined { let witness = typed_array::NewAttachedJSTypedArrayWitness(array); const length: uintptr = witness.Get().length; + + // 6. Repeat, while k < len for (let k: uintptr = 0; k < length; k++) { - // BUG(4895): We should throw on detached buffers rather than simply exit. - witness.Recheck() otherwise break; - const value: JSAny = witness.Load(k); + // 6a. Let Pk be ! ToString(𝔽(k)). + // There is no need to cast ToString to load elements. + + // 6b. Let kValue be ! Get(O, Pk). + // kValue must be undefined when the buffer is detached. + let value: JSAny; + try { + witness.Recheck() otherwise goto IsDetached; + value = witness.Load(k); + } label IsDetached deferred { + value = Undefined; + } + + // 6c. Perform ? Call(callbackfn, thisArg, « kValue, 𝔽(k), O »). // TODO(v8:4153): Consider versioning this loop for Smi and non-Smi // indices to optimize Convert(k) for the most common case. Call( context, callbackfn, thisArg, value, Convert(k), witness.GetStable()); + + // 6d. Set k to k + 1. (done by the loop). } + + // 7. Return undefined. return Undefined; } diff --git a/src/builtins/typed-array-reduce.tq b/src/builtins/typed-array-reduce.tq index a54ed1040e..0261599106 100644 --- a/src/builtins/typed-array-reduce.tq +++ b/src/builtins/typed-array-reduce.tq @@ -12,11 +12,17 @@ transitioning macro ReduceAllElements(implicit context: Context)( initialValue: JSAny|TheHole): JSAny { let witness = typed_array::NewAttachedJSTypedArrayWitness(array); const length: uintptr = witness.Get().length; + let accumulator = initialValue; for (let k: uintptr = 0; k < length; k++) { - // BUG(4895): We should throw on detached buffers rather than simply exit. - witness.Recheck() otherwise break; - const value: JSAny = witness.Load(k); + let value: JSAny; + try { + witness.Recheck() + otherwise goto IsDetached; + value = witness.Load(k); + } label IsDetached deferred { + value = Undefined; + } typeswitch (accumulator) { case (TheHole): { accumulator = value; diff --git a/src/builtins/typed-array-reduceright.tq b/src/builtins/typed-array-reduceright.tq index 9ba2f70de4..5449c4f1fc 100644 --- a/src/builtins/typed-array-reduceright.tq +++ b/src/builtins/typed-array-reduceright.tq @@ -8,6 +8,7 @@ namespace typed_array { const kBuiltinNameReduceRight: constexpr string = '%TypedArray%.prototype.reduceRight'; +// https://tc39.github.io/ecma262/#sec-%typedarray%.prototype.reduceright transitioning macro ReduceRightAllElements(implicit context: Context)( array: typed_array::AttachedJSTypedArray, callbackfn: Callable, initialValue: JSAny|TheHole): JSAny { @@ -15,9 +16,14 @@ transitioning macro ReduceRightAllElements(implicit context: Context)( const length: uintptr = witness.Get().length; let accumulator = initialValue; for (let k: uintptr = length; k-- > 0;) { - // BUG(4895): We should throw on detached buffers rather than simply exit. - witness.Recheck() otherwise break; - const value: JSAny = witness.Load(k); + let value: JSAny; + try { + witness.Recheck() + otherwise goto IsDetached; + value = witness.Load(k); + } label IsDetached deferred { + value = Undefined; + } typeswitch (accumulator) { case (TheHole): { accumulator = value; diff --git a/src/builtins/typed-array-some.tq b/src/builtins/typed-array-some.tq index ecdfae1e8a..9946907680 100644 --- a/src/builtins/typed-array-some.tq +++ b/src/builtins/typed-array-some.tq @@ -7,24 +7,45 @@ namespace typed_array { const kBuiltinNameSome: constexpr string = '%TypedArray%.prototype.some'; +// https://tc39.es/ecma262/#sec-%typedarray%.prototype.some transitioning macro SomeAllElements(implicit context: Context)( array: typed_array::AttachedJSTypedArray, callbackfn: Callable, thisArg: JSAny): Boolean { let witness = typed_array::NewAttachedJSTypedArrayWitness(array); const length: uintptr = witness.Get().length; + + // 6. Repeat, while k < len for (let k: uintptr = 0; k < length; k++) { - // BUG(4895): We should throw on detached buffers rather than simply exit. - witness.Recheck() otherwise break; - const value: JSAny = witness.Load(k); + // 6a. Let Pk be ! ToString(𝔽(k)). + // There is no need to cast ToString to load elements. + + // 6b. Let kValue be ! Get(O, Pk). + // kValue must be undefined when the buffer is detached. + let value: JSAny; + try { + witness.Recheck() otherwise goto IsDetached; + value = witness.Load(k); + } label IsDetached deferred { + value = Undefined; + } + + // 6c. Let testResult be ! ToBoolean(? Call(callbackfn, thisArg, « kValue, + // 𝔽(k), O »)). // TODO(v8:4153): Consider versioning this loop for Smi and non-Smi // indices to optimize Convert(k) for the most common case. const result = Call( context, callbackfn, thisArg, value, Convert(k), witness.GetStable()); + + // 6d. If testResult is true, return true. if (ToBoolean(result)) { return True; } + + // 6e. Set k to k + 1. (done by the loop). } + + // 7. Return false. return False; } @@ -41,6 +62,7 @@ TypedArrayPrototypeSome( const callbackfn = Cast(arguments[0]) otherwise NotCallable; const thisArg = arguments[1]; + return SomeAllElements(uarray, callbackfn, thisArg); } label NotCallable deferred { ThrowTypeError(MessageTemplate::kCalledNonCallable, arguments[0]); diff --git a/test/mjsunit/es6/typedarray-every.js b/test/mjsunit/es6/typedarray-every.js index feb7cc90cc..a4a3f7c8d8 100644 --- a/test/mjsunit/es6/typedarray-every.js +++ b/test/mjsunit/es6/typedarray-every.js @@ -82,18 +82,16 @@ function TestTypedArrayForEach(constructor) { CheckWrapping({}, Object); // Detaching the buffer backing the typed array mid-way should - // still make .forEach() finish, and the array should keep being + // still make .every() finish, and the array should keep being // empty after detaching it. count = 0; a = new constructor(3); result = a.every(function (n, index, array) { - assertFalse(array[index] === undefined); // don't get here if detached - if (count > 0) %ArrayBufferDetach(array.buffer); - array[index] = n + 1; count++; - return count > 1 ? array[index] === undefined : true; + if (count > 1) %ArrayBufferDetach(array.buffer); + return count > 2 ? n === undefined : true; }); - assertEquals(2, count); + assertEquals(3, count); assertEquals(true, result); CheckTypedArrayIsDetached(a); assertEquals(undefined, a[0]); diff --git a/test/mjsunit/es6/typedarray-filter.js b/test/mjsunit/es6/typedarray-filter.js index 077016a26c..2d2ef5d1ee 100644 --- a/test/mjsunit/es6/typedarray-filter.js +++ b/test/mjsunit/es6/typedarray-filter.js @@ -19,10 +19,22 @@ function TestTypedArrayFilter(constructor) { assertEquals(1, constructor.prototype.filter.length); // Throw type error if source array is detached while executing a callback - let ta1 = new constructor(10); - assertThrows(() => - ta1.filter(() => %ArrayBufferDetach(ta1.buffer)) - , TypeError); + let ta1 = new constructor(4); + let seen = []; + let result = ta1.filter((val, idx) => { + if (idx === 0) { + %ArrayBufferDetach(ta1.buffer); + } + seen.push(val); + return idx < 3; + }); + assertArrayEquals(seen, [0, undefined, undefined, undefined]); + // https://tc39.es/ecma262/#sec-setvalueinbuffer + // undefined values should be converted to numerics. + const expectedResult = [Float32Array, Float64Array].includes(constructor) ? + [0, NaN, NaN] : + [0, 0, 0]; + assertArrayEquals(result, expectedResult); // A new typed array should be created after finishing callbacks var speciesCreated = 0; diff --git a/test/mjsunit/es6/typedarray-foreach.js b/test/mjsunit/es6/typedarray-foreach.js index 81c212046a..413cf68105 100644 --- a/test/mjsunit/es6/typedarray-foreach.js +++ b/test/mjsunit/es6/typedarray-foreach.js @@ -85,20 +85,18 @@ function TestTypedArrayForEach(constructor) { assertEquals(42, a[1]); // Detaching the buffer backing the typed array mid-way should - // still make .forEach() finish, but exiting early due to the missing - // elements, and the array should keep being empty after detaching it. - // TODO(dehrenberg): According to the ES6 spec, accessing or testing - // for members on a detached TypedArray should throw, so really this - // should throw in the third iteration. However, this behavior matches - // the Khronos spec. + // still make .forEach() finish, but the first argument of the callback + // should be undefined value, and the array should keep being empty after + // detaching it. a = new constructor(3); count = 0; a.forEach(function (n, index, array) { if (count > 0) %ArrayBufferDetach(array.buffer); + if (count > 1) assertTrue(n === undefined); array[index] = n + 1; count++; }); - assertEquals(2, count); + assertEquals(3, count); CheckTypedArrayIsDetached(a); assertEquals(undefined, a[0]); diff --git a/test/test262/test262.status b/test/test262/test262.status index 8d51d90271..6d22377ec5 100644 --- a/test/test262/test262.status +++ b/test/test262/test262.status @@ -69,28 +69,8 @@ # https://code.google.com/p/v8/issues/detail?id=10958 'language/module-code/eval-gtbndng-indirect-faux-assertion': [FAIL], - # https://bugs.chromium.org/p/v8/issues/detail?id=4895 - # Some TypedArray methods throw due to the same bug, from Get - 'built-ins/TypedArray/prototype/every/callbackfn-detachbuffer': [FAIL], - 'built-ins/TypedArray/prototype/every/BigInt/callbackfn-detachbuffer': [FAIL], - 'built-ins/TypedArray/prototype/filter/callbackfn-detachbuffer': [FAIL], - 'built-ins/TypedArray/prototype/filter/BigInt/callbackfn-detachbuffer': [FAIL], - 'built-ins/TypedArray/prototype/find/predicate-may-detach-buffer': [FAIL], - 'built-ins/TypedArray/prototype/find/BigInt/predicate-may-detach-buffer': [FAIL], - 'built-ins/TypedArray/prototype/findIndex/predicate-may-detach-buffer': [FAIL], - 'built-ins/TypedArray/prototype/findIndex/BigInt/predicate-may-detach-buffer': [FAIL], - 'built-ins/TypedArray/prototype/forEach/callbackfn-detachbuffer': [FAIL], - 'built-ins/TypedArray/prototype/forEach/BigInt/callbackfn-detachbuffer': [FAIL], - 'built-ins/TypedArray/prototype/map/callbackfn-detachbuffer': [FAIL], - 'built-ins/TypedArray/prototype/map/BigInt/callbackfn-detachbuffer': [FAIL], - 'built-ins/TypedArray/prototype/reduce/callbackfn-detachbuffer': [FAIL], - 'built-ins/TypedArray/prototype/reduce/BigInt/callbackfn-detachbuffer': [FAIL], - 'built-ins/TypedArray/prototype/reduceRight/callbackfn-detachbuffer': [FAIL], - 'built-ins/TypedArray/prototype/reduceRight/BigInt/callbackfn-detachbuffer': [FAIL], 'built-ins/TypedArray/prototype/set/array-arg-primitive-toobject': [FAIL], 'built-ins/TypedArray/prototype/set/BigInt/array-arg-primitive-toobject': [FAIL], - 'built-ins/TypedArray/prototype/some/callbackfn-detachbuffer': [FAIL], - 'built-ins/TypedArray/prototype/some/BigInt/callbackfn-detachbuffer': [FAIL], # DataView functions should also throw on detached buffers 'built-ins/DataView/detached-buffer': [FAIL], 'built-ins/DataView/prototype/byteLength/detached-buffer': [FAIL],