diff --git a/ecmascript/base/typed_array_helper.cpp b/ecmascript/base/typed_array_helper.cpp index ef7279a802a3c1a50005f6a98e928a45ba4f8926..c18ee7b113d80937b1809d90b069a4a081bb8902 100644 --- a/ecmascript/base/typed_array_helper.cpp +++ b/ecmascript/base/typed_array_helper.cpp @@ -72,6 +72,20 @@ JSTaggedValue TypedArrayHelper::TypedArrayConstructor(EcmaRuntimeCallInfo *argv, JSHandle obj = TypedArrayHelper::AllocateTypedArray(thread, constructorName, newTarget, arrayType); RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread); + + // 5. Let usingIterator be ? GetMethod(object, @@iterator). + EcmaVM *ecmaVm = thread->GetEcmaVM(); + JSHandle env = ecmaVm->GetGlobalEnv(); + JSHandle object(firstArg); + JSHandle iteratorSymbol = env->GetIteratorSymbol(); + JSHandle usingIterator = + JSObject::GetMethod(thread, JSHandle::Cast(object), iteratorSymbol); + RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread); + // 6. If usingIterator is not undefined, then + if (!usingIterator->IsUndefined()) { + return TypedArrayHelper::CreateFromIteratorObject(argv, obj, arrayType, usingIterator); + } + if (firstArg->IsTypedArray()) { return TypedArrayHelper::CreateFromTypedArray(argv, obj, arrayType); } @@ -114,58 +128,7 @@ JSTaggedValue TypedArrayHelper::CreateFromOrdinaryObject(EcmaRuntimeCallInfo *ar { ASSERT(argv); JSThread *thread = argv->GetThread(); - [[maybe_unused]] EcmaHandleScope handleScope(thread); - EcmaVM *ecmaVm = thread->GetEcmaVM(); - JSHandle env = ecmaVm->GetGlobalEnv(); JSHandle objectArg = BuiltinsBase::GetCallArg(argv, 0); - JSHandle object(objectArg); - // 5. Let usingIterator be ? GetMethod(object, @@iterator). - JSHandle iteratorSymbol = env->GetIteratorSymbol(); - JSHandle usingIterator = - JSObject::GetMethod(thread, JSHandle::Cast(object), iteratorSymbol); - RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread); - - // 6. If usingIterator is not undefined, then - if (!usingIterator->IsUndefined()) { - CVector> vec; - // a. Let values be ? IterableToList(object, usingIterator). - // b. Let len be the number of elements in values. - // c. Perform ? AllocateTypedArrayBuffer(O, len). - JSHandle iterator = JSIterator::GetIterator(thread, objectArg, usingIterator); - RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread); - JSHandle next(thread, JSTaggedValue::True()); - while (!next->IsFalse()) { - next = JSIterator::IteratorStep(thread, iterator); - RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread); - if (!next->IsFalse()) { - JSHandle nextValue = JSIterator::IteratorValue(thread, next); - vec.push_back(nextValue); - } - } - uint32_t len = static_cast(vec.size()); - TypedArrayHelper::AllocateTypedArrayBuffer(thread, obj, len, arrayType); - RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread); - // d. Let k be 0. - // e. Repeat, while k < len - // i. Let Pk be ! ToString(k). - // ii. Let kValue be the first element of values and remove that element from values. - // iii. Perform ? Set(O, Pk, kValue, true). - // iv. Set k to k + 1. - JSMutableHandle tKey(thread, JSTaggedValue::Undefined()); - uint32_t k = 0; - while (k < len) { - tKey.Update(JSTaggedValue(k)); - JSHandle kKey(JSTaggedValue::ToString(thread, tKey)); - RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread); - JSHandle kValue = vec[k]; - JSTaggedValue::SetProperty(thread, JSHandle::Cast(obj), kKey, kValue, true); - RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread); - k++; - } - // f. Assert: values is now an empty List. - // g. Return O. - return obj.GetTaggedValue(); - } // 7. NOTE: object is not an Iterable so assume it is already an array-like object. // 8. Let arrayLike be object. @@ -201,6 +164,52 @@ JSTaggedValue TypedArrayHelper::CreateFromOrdinaryObject(EcmaRuntimeCallInfo *ar return obj.GetTaggedValue(); } +// es11 22.2.4.4 TypedArray ( Iterator ) +JSTaggedValue TypedArrayHelper::CreateFromIteratorObject(EcmaRuntimeCallInfo *argv, const JSHandle &obj, + const DataViewType arrayType, JSHandle usingIterator) +{ + JSThread *thread = argv->GetThread(); + JSHandle objectArg = BuiltinsBase::GetCallArg(argv, 0); + CVector> vec; + // a. Let values be ? IterableToList(object, usingIterator). + // b. Let len be the number of elements in values. + // c. Perform ? AllocateTypedArrayBuffer(O, len). + JSHandle iterator = JSIterator::GetIterator(thread, objectArg, usingIterator); + RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread); + JSHandle next(thread, JSTaggedValue::True()); + while (!next->IsFalse()) { + next = JSIterator::IteratorStep(thread, iterator); + RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread); + if (!next->IsFalse()) { + JSHandle nextValue = JSIterator::IteratorValue(thread, next); + vec.push_back(nextValue); + } + } + uint32_t len = static_cast(vec.size()); + TypedArrayHelper::AllocateTypedArrayBuffer(thread, obj, len, arrayType); + RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread); + // d. Let k be 0. + // e. Repeat, while k < len + // i. Let Pk be ! ToString(k). + // ii. Let kValue be the first element of values and remove that element from values. + // iii. Perform ? Set(O, Pk, kValue, true). + // iv. Set k to k + 1. + JSMutableHandle tKey(thread, JSTaggedValue::Undefined()); + uint32_t k = 0; + while (k < len) { + tKey.Update(JSTaggedValue(k)); + JSHandle kKey(JSTaggedValue::ToString(thread, tKey)); + RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread); + JSHandle kValue = vec[k]; + JSTaggedValue::SetProperty(thread, JSHandle::Cast(obj), kKey, kValue, true); + RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread); + k++; + } + // f. Assert: values is now an empty List. + // g. Return O. + return obj.GetTaggedValue(); +} + // es11 22.2.4.3 TypedArray ( typedArray ) JSTaggedValue TypedArrayHelper::CreateFromTypedArray(EcmaRuntimeCallInfo *argv, const JSHandle &obj, const DataViewType arrayType) diff --git a/ecmascript/base/typed_array_helper.h b/ecmascript/base/typed_array_helper.h index 5cb0a899170836da1f92be50b7e358b18cb5d8e4..89461b4ff47f15a97eb9a74c30094d99d86b107d 100644 --- a/ecmascript/base/typed_array_helper.h +++ b/ecmascript/base/typed_array_helper.h @@ -85,6 +85,8 @@ private: uint64_t length, const DataViewType arrayType); static JSTaggedValue FastCopyElementFromArray(EcmaRuntimeCallInfo *argv, const JSHandle &obj, const DataViewType arrayType); + static JSTaggedValue CreateFromIteratorObject(EcmaRuntimeCallInfo *argv, const JSHandle &obj, + const DataViewType arrayType, JSHandle usingIterator); }; } // namespace panda::ecmascript::base