diff --git a/ecmascript/builtins/builtins_array.cpp b/ecmascript/builtins/builtins_array.cpp index 83f12a88b69b7f8ab45d57c917f04f8dd2c154d9..09b6957aa7ac89ad979b270c80684fdc0fcb698c 100644 --- a/ecmascript/builtins/builtins_array.cpp +++ b/ecmascript/builtins/builtins_array.cpp @@ -1270,7 +1270,22 @@ JSTaggedValue BuiltinsArray::Join(EcmaRuntimeCallInfo *argv) JSHandle thisObjVal(thisObjHandle); // 3. Let len be ToLength(Get(O, "length")). - int64_t len = ArrayHelper::GetLength(thread, thisObjVal); + int64_t propertyLen = 0; + int64_t len = 0; + if (thisHandle->IsTypedArray()) { + JSHandle lengthKey = thread->GlobalConstants()->GetHandledLengthString(); + JSHandle lenResult = JSTaggedValue::GetProperty(thread, thisHandle, lengthKey).GetValue(); + if (!(thread)->HasPendingException()) { + propertyLen = JSTaggedValue::ToLength(thread, lenResult).GetNumber(); + } + } + len = ArrayHelper::GetLength(thread, thisObjVal); + if (thisHandle->IsTypedArray()) { + if (propertyLen != len && propertyLen < len) { + len = propertyLen; + } + } + if (len > UINT32_MAX) { THROW_TYPE_ERROR_AND_RETURN(thread, "Invalid array length", JSTaggedValue::Exception()); } @@ -2544,7 +2559,22 @@ JSTaggedValue BuiltinsArray::ToLocaleString(EcmaRuntimeCallInfo *argv) JSHandle thisObjVal(thisObjHandle); // 3. Let len be ToLength(Get(O, "length")). - int64_t len = ArrayHelper::GetLength(thread, thisObjVal); + int64_t propertyLen = 0; + int64_t len = 0; + if (thisHandle->IsTypedArray()) { + JSHandle lengthKey = thread->GlobalConstants()->GetHandledLengthString(); + JSHandle lenResult = JSTaggedValue::GetProperty(thread, thisHandle, lengthKey).GetValue(); + if (!(thread)->HasPendingException()) { + propertyLen = JSTaggedValue::ToLength(thread, lenResult).GetNumber(); + } + } + len = ArrayHelper::GetLength(thread, thisObjVal); + if (thisHandle->IsTypedArray()) { + if (propertyLen != len && propertyLen < len) { + len = propertyLen; + } + } + // 4. ReturnIfAbrupt(len). RETURN_EXCEPTION_AND_POP_JOINSTACK(thread, thisHandle); diff --git a/ecmascript/builtins/builtins_typedarray.cpp b/ecmascript/builtins/builtins_typedarray.cpp index 05b6e20918cf00f41ee1c7d11127bd802a0a0bc8..0c6b94b6a2c1d2954e34e929b0ef65e4959460a3 100644 --- a/ecmascript/builtins/builtins_typedarray.cpp +++ b/ecmascript/builtins/builtins_typedarray.cpp @@ -1595,7 +1595,93 @@ JSTaggedValue BuiltinsTypedArray::ToLocaleString(EcmaRuntimeCallInfo *argv) if (!GetThis(argv)->IsTypedArray()) { THROW_TYPE_ERROR_AND_RETURN(argv->GetThread(), "This is not a TypedArray.", JSTaggedValue::Exception()); } - return BuiltinsArray::ToLocaleString(argv); + JSThread *thread = argv->GetThread(); + [[maybe_unused]] EcmaHandleScope handleScope(thread); + auto ecmaVm = thread->GetEcmaVM(); + ObjectFactory *factory = ecmaVm->GetFactory(); + + // 1. Let O be ToObject(this value). + JSHandle thisHandle = GetThis(argv); + JSHandle thisObjHandle = JSTaggedValue::ToObject(thread, thisHandle); + // add this to join stack to avoid circular call + auto context = thread->GetCurrentEcmaContext(); + bool noCircular = context->JoinStackPushFastPath(thisHandle); + if (!noCircular) { + return factory->GetEmptyString().GetTaggedValue(); + } + // 2. ReturnIfAbrupt(O). + RETURN_EXCEPTION_AND_POP_JOINSTACK(thread, thisHandle); + JSHandle thisObjVal(thisObjHandle); + + // 3. Let len be ToLength(Get(O, "length")). + int64_t len = JSHandle::Cast(thisHandle)->GetArrayLength(); + // 4. ReturnIfAbrupt(len). + RETURN_EXCEPTION_AND_POP_JOINSTACK(thread, thisHandle); + + // 6. If len is zero, return the empty String. + if (len == 0) { + // pop this from join stack + context->JoinStackPopFastPath(thisHandle); + return GetTaggedString(thread, ""); + } + + // Inject locales and options argument into a taggedArray + JSHandle locales = GetCallArg(argv, 0); + JSHandle options = GetCallArg(argv, 1); + + CString concatStr; + // 7. Let firstElement be Get(array, "0"). + // 8. ReturnIfAbrupt(firstElement). + // 9. If firstElement is undefined or null, then + // a. Let R be the empty String. + // 10. Else + // a. Let R be ToString(Invoke(firstElement, "toLocaleString")). + // b. ReturnIfAbrupt(R). + // 11. Let k be 1. + // 12. Repeat, while k < len + // a. Let S be a String value produced by concatenating R and separator. + // b. Let nextElement be Get(array, ToString(k)). + // c. ReturnIfAbrupt(nextElement). + // d. If nextElement is undefined or null, then + // i. Let R be the empty String. + // e. Else + // i. Let R be ToString(Invoke(nextElement, "toLocaleString")). + // ii. ReturnIfAbrupt(R). + // f. Let R be a String value produced by concatenating S and R. + // g. Increase k by 1. + auto globalConst = thread->GlobalConstants(); + JSHandle undefined = globalConst->GetHandledUndefined(); + for (int64_t k = 0; k < len; k++) { + JSTaggedValue next = globalConst->GetEmptyString(); + JSHandle nextElement = JSArray::FastGetPropertyByValue(thread, thisObjVal, k); + RETURN_EXCEPTION_AND_POP_JOINSTACK(thread, thisHandle); + if (!nextElement->IsUndefined() && !nextElement->IsNull()) { + JSHandle nextValueHandle = nextElement; + JSHandle key = globalConst->GetHandledToLocaleStringString(); + EcmaRuntimeCallInfo *info = + EcmaInterpreter::NewRuntimeCallInfo(thread, undefined, nextValueHandle, undefined, 2); // 2: two args + RETURN_EXCEPTION_AND_POP_JOINSTACK(thread, thisHandle); + info->SetCallArg(locales.GetTaggedValue(), options.GetTaggedValue()); + JSTaggedValue callResult = JSFunction::Invoke(info, key); + RETURN_EXCEPTION_AND_POP_JOINSTACK(thread, thisHandle); + next = callResult; + } + JSHandle nextHandle(thread, next); + JSHandle nextStringHandle = JSTaggedValue::ToString(thread, nextHandle); + RETURN_EXCEPTION_AND_POP_JOINSTACK(thread, thisHandle); + CString nextString = ConvertToString(*nextStringHandle); + if (k > 0) { + concatStr += STRING_SEPERATOR; + concatStr += nextString; + continue; + } + concatStr += nextString; + } + + // pop this from join stack + context->JoinStackPopFastPath(thisHandle); + // 13. Return R. + return factory->NewFromUtf8(concatStr).GetTaggedValue(); } // 22.2.3.28 diff --git a/test/regresstest/regresstest_skip_tests.json b/test/regresstest/regresstest_skip_tests.json index 721f3145e96d9b9dba43972daff1f81c93f6c9a2..0fdabd3a15ac3cfac87b4b07615b488fdfcdbbcc 100644 --- a/test/regresstest/regresstest_skip_tests.json +++ b/test/regresstest/regresstest_skip_tests.json @@ -3014,7 +3014,6 @@ "mjsunit/es6/block-for-sloppy.js", "mjsunit/es6/computed-property-names-classes.js", "mjsunit/es6/unicode-character-ranges.js", - "mjsunit/es6/typedarray-tostring.js", "mjsunit/es6/map-iterator-7.js", "mjsunit/es6/object-tostring.js", "mjsunit/es6/typedarray-set-bytelength-not-smi.js",