mirror of
https://gitee.com/openharmony/arkcompiler_ets_runtime
synced 2025-02-17 10:18:13 +00:00
string.localecompare
Signed-off-by: gwl <guowanlong@huawei.com> Change-Id: I7c61fab62ee92c32be66a52b4f46d0f8659153ee
This commit is contained in:
parent
d29a1082fb
commit
455fd02b7e
@ -568,6 +568,30 @@ JSTaggedValue BuiltinsString::LocaleCompare(EcmaRuntimeCallInfo *argv)
|
||||
#endif
|
||||
}
|
||||
|
||||
JSTaggedValue BuiltinsString::LocaleCompareGC(JSThread *thread, JSHandle<JSTaggedValue> locales,
|
||||
JSHandle<EcmaString> thisHandle, JSHandle<EcmaString> thatHandle,
|
||||
JSHandle<JSTaggedValue> options, bool cacheable)
|
||||
{
|
||||
EcmaVM *ecmaVm = thread->GetEcmaVM();
|
||||
ObjectFactory *factory = ecmaVm->GetFactory();
|
||||
JSHandle<JSTaggedValue> ctor = ecmaVm->GetGlobalEnv()->GetCollatorFunction();
|
||||
JSHandle<JSCollator> collator =
|
||||
JSHandle<JSCollator>::Cast(factory->NewJSObjectByConstructor(JSHandle<JSFunction>(ctor)));
|
||||
JSHandle<JSCollator> initCollator =
|
||||
JSCollator::InitializeCollator(thread, collator, locales, options, cacheable);
|
||||
RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
|
||||
icu::Collator *icuCollator = nullptr;
|
||||
if (cacheable) {
|
||||
icuCollator = JSCollator::GetCachedIcuCollator(thread, locales);
|
||||
ASSERT(icuCollator != nullptr);
|
||||
} else {
|
||||
icuCollator = initCollator->GetIcuCollator();
|
||||
}
|
||||
JSTaggedValue result = JSCollator::CompareStrings(icuCollator, thisHandle, thatHandle);
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
// 21.1.3.11
|
||||
JSTaggedValue BuiltinsString::Match(EcmaRuntimeCallInfo *argv)
|
||||
{
|
||||
|
@ -159,6 +159,9 @@ public:
|
||||
static JSTaggedValue LastIndexOf(EcmaRuntimeCallInfo *argv);
|
||||
// 21.1.3.10
|
||||
static JSTaggedValue LocaleCompare(EcmaRuntimeCallInfo *argv);
|
||||
static JSTaggedValue LocaleCompareGC(JSThread *thread, JSHandle<JSTaggedValue> locales,
|
||||
JSHandle<EcmaString> thisHandle, JSHandle<EcmaString> thatHandle,
|
||||
JSHandle<JSTaggedValue> options, bool cacheable);
|
||||
// 21.1.3.11
|
||||
static JSTaggedValue Match(EcmaRuntimeCallInfo *argv);
|
||||
|
||||
|
@ -29,7 +29,8 @@ namespace panda::ecmascript::kungfu {
|
||||
// AOT_BUILTINS_STUB_LIST is used in AOT only.
|
||||
#define BUILTINS_STUB_LIST(V) \
|
||||
BUILTINS_METHOD_STUB_LIST(V) \
|
||||
BUILTINS_CONSTRUCTOR_STUB_LIST(V)
|
||||
BUILTINS_CONSTRUCTOR_STUB_LIST(V) \
|
||||
AOT_AND_BUILTINS_STUB_LIST(V)
|
||||
|
||||
#define BUILTINS_METHOD_STUB_LIST(V) \
|
||||
V(StringCharCodeAt) \
|
||||
@ -89,6 +90,9 @@ namespace panda::ecmascript::kungfu {
|
||||
V(DateConstructor) \
|
||||
V(ArrayConstructor)
|
||||
|
||||
#define AOT_AND_BUILTINS_STUB_LIST(V) \
|
||||
V(LocaleCompare)
|
||||
|
||||
#define AOT_BUILTINS_STUB_LIST(V) \
|
||||
V(SQRT) /* list start and math list start */ \
|
||||
V(COS) \
|
||||
@ -97,7 +101,6 @@ namespace panda::ecmascript::kungfu {
|
||||
V(ATAN) \
|
||||
V(ABS) \
|
||||
V(FLOOR) /* math list end */ \
|
||||
V(LocaleCompare) \
|
||||
V(SORT) \
|
||||
V(STRINGIFY) \
|
||||
V(MAP_PROTO_ITERATOR) \
|
||||
@ -163,8 +166,9 @@ public:
|
||||
|
||||
static bool IsTypedBuiltin(ID builtinId)
|
||||
{
|
||||
return (BuiltinsStubCSigns::ID::TYPED_BUILTINS_FIRST <= builtinId) &&
|
||||
(builtinId <= BuiltinsStubCSigns::ID::TYPED_BUILTINS_LAST);
|
||||
return (BuiltinsStubCSigns::ID::LocaleCompare == builtinId) ||
|
||||
((BuiltinsStubCSigns::ID::TYPED_BUILTINS_FIRST <= builtinId) &&
|
||||
(builtinId <= BuiltinsStubCSigns::ID::TYPED_BUILTINS_LAST));
|
||||
}
|
||||
|
||||
static bool IsTypedBuiltinMath(ID builtinId)
|
||||
|
@ -1840,6 +1840,58 @@ GateRef BuiltinsStringStubBuilder::StringConcat(GateRef glue, GateRef leftString
|
||||
return ret;
|
||||
}
|
||||
|
||||
void BuiltinsStringStubBuilder::LocaleCompare([[maybe_unused]] GateRef glue, GateRef thisValue, GateRef numArgs,
|
||||
[[maybe_unused]] Variable *res, [[maybe_unused]] Label *exit,
|
||||
Label *slowPath)
|
||||
{
|
||||
auto env = GetEnvironment();
|
||||
|
||||
Label thisIsHeapObj(env);
|
||||
Branch(TaggedIsHeapObject(thisValue), &thisIsHeapObj, slowPath);
|
||||
Bind(&thisIsHeapObj);
|
||||
{
|
||||
Label thisValueIsString(env);
|
||||
Label fristArgIsString(env);
|
||||
Label arg0IsHeapObj(env);
|
||||
Branch(IsString(thisValue), &thisValueIsString, slowPath);
|
||||
Bind(&thisValueIsString);
|
||||
GateRef arg0 = GetCallArg0(numArgs);
|
||||
Branch(TaggedIsHeapObject(arg0), &arg0IsHeapObj, slowPath);
|
||||
Bind(&arg0IsHeapObj);
|
||||
Branch(IsString(arg0), &fristArgIsString, slowPath);
|
||||
Bind(&fristArgIsString);
|
||||
#ifdef ARK_SUPPORT_INTL
|
||||
GateRef locales = GetCallArg1(numArgs);
|
||||
|
||||
GateRef options = GetCallArg2(numArgs);
|
||||
GateRef localesIsUndef = TaggedIsUndefined(locales);
|
||||
GateRef optionsIsUndef = TaggedIsUndefined(options);
|
||||
GateRef cacheable = BoolAnd(BoolOr(localesIsUndef, TaggedObjectIsString(locales)), optionsIsUndef);
|
||||
Label optionsIsString(env);
|
||||
Label cacheAble(env);
|
||||
Label uncacheable(env);
|
||||
|
||||
Branch(cacheable, &cacheAble, &uncacheable);
|
||||
Bind(&cacheAble);
|
||||
{
|
||||
Label defvalue(env);
|
||||
GateRef resValue = CallNGCRuntime(glue, RTSTUB_ID(LocaleCompareNoGc), {glue, locales, thisValue, arg0});
|
||||
Branch(TaggedIsUndefined(resValue), slowPath, &defvalue);
|
||||
Bind(&defvalue);
|
||||
*res = resValue;
|
||||
Jump(exit);
|
||||
}
|
||||
Bind(&uncacheable);
|
||||
{
|
||||
res->WriteVariable(CallRuntime(glue, RTSTUB_ID(LocaleCompareWithGc), {locales, thisValue, arg0, options}));
|
||||
Jump(exit);
|
||||
}
|
||||
#else
|
||||
Jump(slowPath);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
GateRef BuiltinsStringStubBuilder::EcmaStringTrim(GateRef glue, GateRef srcString, GateRef trimMode)
|
||||
{
|
||||
auto env = GetEnvironment();
|
||||
|
@ -38,6 +38,7 @@ public:
|
||||
void Replace(GateRef glue, GateRef thisValue, GateRef numArgs, Variable *res, Label *exit, Label *slowPath);
|
||||
void Trim(GateRef glue, GateRef thisValue, GateRef numArgs, Variable *res, Label *exit, Label *slowPath);
|
||||
void Slice(GateRef glue, GateRef thisValue, GateRef numArgs, Variable *res, Label *exit, Label *slowPath);
|
||||
void LocaleCompare(GateRef glue, GateRef thisValue, GateRef numArgs, Variable *res, Label *exit, Label *slowPath);
|
||||
|
||||
GateRef ConvertAndClampRelativeIndex(GateRef index, GateRef length);
|
||||
GateRef StringAt(const StringInfoGateRef &stringInfoGate, GateRef index);
|
||||
|
@ -177,6 +177,24 @@ DECLARE_BUILTINS(String##method)
|
||||
V(Trim, JS_ANY, Undefined()) \
|
||||
V(Slice, JS_ANY, Undefined())
|
||||
|
||||
DECLARE_BUILTINS(LocaleCompare)
|
||||
{
|
||||
auto env = GetEnvironment();
|
||||
DEFVARIABLE(res, VariableType::JS_ANY(), Undefined());
|
||||
Label exit(env);
|
||||
Label slowPath(env);
|
||||
BuiltinsStringStubBuilder stringStubBuilder(this);
|
||||
stringStubBuilder.LocaleCompare(glue, thisValue, numArgs, &res, &exit, &slowPath);
|
||||
Bind(&slowPath);
|
||||
{
|
||||
auto name = BuiltinsStubCSigns::GetName(BUILTINS_STUB_ID(LocaleCompare));
|
||||
res = CallSlowPath(nativeCode, glue, thisValue, numArgs, func, newTarget, name.c_str());
|
||||
Jump(&exit);
|
||||
}
|
||||
Bind(&exit);
|
||||
Return(*res);
|
||||
}
|
||||
|
||||
BUILTINS_WITH_STRING_STUB_BUILDER(DECLARE_BUILTINS_WITH_STRING_STUB_BUILDER)
|
||||
|
||||
#undef DECLARE_BUILTINS_WITH_STRING_STUB_BUILDER
|
||||
|
@ -1209,6 +1209,23 @@ DEF_CALL_SIGNATURE(BigIntEquals)
|
||||
callSign->SetTargetKind(CallSignature::TargetKind::RUNTIME_STUB_NO_GC);
|
||||
}
|
||||
|
||||
DEF_CALL_SIGNATURE(LocaleCompareNoGc)
|
||||
{
|
||||
// 4 : 4 input parameters
|
||||
CallSignature localeCompareNoGc("LocaleCompareNoGc", 0, 4,
|
||||
ArgumentsOrder::DEFAULT_ORDER, VariableType::JS_ANY());
|
||||
*callSign = localeCompareNoGc;
|
||||
std::array<VariableType, 4> params = { // 4 : 4 input parameters
|
||||
VariableType::NATIVE_POINTER(),
|
||||
VariableType::JS_POINTER(),
|
||||
VariableType::JS_POINTER(),
|
||||
VariableType::JS_POINTER(),
|
||||
};
|
||||
callSign->SetParameters(params.data());
|
||||
callSign->SetGCLeafFunction(true);
|
||||
callSign->SetTargetKind(CallSignature::TargetKind::RUNTIME_STUB_NO_GC);
|
||||
}
|
||||
|
||||
DEF_CALL_SIGNATURE(BigIntSameValueZero)
|
||||
{
|
||||
// 1 : 1 input parameters
|
||||
|
@ -471,6 +471,7 @@ private:
|
||||
V(CreateJSMapIterator) \
|
||||
V(JSHClassFindProtoTransitions) \
|
||||
V(NumberHelperStringToDouble) \
|
||||
V(LocaleCompareNoGc) \
|
||||
V(StringGetStart) \
|
||||
V(StringGetEnd)
|
||||
|
||||
|
@ -1147,6 +1147,25 @@ inline GateRef StubBuilder::IsString(GateRef obj)
|
||||
return res;
|
||||
}
|
||||
|
||||
inline GateRef StubBuilder::TaggedObjectIsString(GateRef obj)
|
||||
{
|
||||
auto env = GetEnvironment();
|
||||
Label entryPass(env);
|
||||
env->SubCfgEntry(&entryPass);
|
||||
DEFVARIABLE(result, VariableType::BOOL(), False());
|
||||
Label heapObj(env);
|
||||
Label exit(env);
|
||||
GateRef isHeapObject = TaggedIsHeapObject(obj);
|
||||
Branch(isHeapObject, &heapObj, &exit);
|
||||
Bind(&heapObj);
|
||||
result = env_->GetBuilder()->TaggedObjectIsString(obj);
|
||||
Jump(&exit);
|
||||
Bind(&exit);
|
||||
auto ret = *result;
|
||||
env->SubCfgExit();
|
||||
return ret;
|
||||
}
|
||||
|
||||
inline GateRef StubBuilder::IsLineString(GateRef obj)
|
||||
{
|
||||
GateRef objectType = GetObjectType(LoadHClass(obj));
|
||||
|
@ -310,6 +310,7 @@ public:
|
||||
GateRef IsEcmaObject(GateRef obj);
|
||||
GateRef IsSymbol(GateRef obj);
|
||||
GateRef IsString(GateRef obj);
|
||||
GateRef TaggedObjectIsString(GateRef obj);
|
||||
GateRef IsLineString(GateRef obj);
|
||||
GateRef IsSlicedString(GateRef obj);
|
||||
GateRef IsConstantString(GateRef obj);
|
||||
|
@ -75,7 +75,8 @@ enum class IcuFormatterType {
|
||||
SIMPLE_DATE_FORMAT_DATE,
|
||||
SIMPLE_DATE_FORMAT_TIME,
|
||||
NUMBER_FORMATTER,
|
||||
COLLATOR
|
||||
COLLATOR,
|
||||
ICU_FORMATTER_TYPE_COUNT
|
||||
};
|
||||
|
||||
using HostPromiseRejectionTracker = void (*)(const EcmaVM* vm,
|
||||
@ -273,32 +274,27 @@ public:
|
||||
IcuDeleteEntry deleteEntry = nullptr)
|
||||
{
|
||||
EcmaContext::IcuFormatter icuFormatter = IcuFormatter(locale, icuObj, deleteEntry);
|
||||
icuObjCache_.insert_or_assign(type, std::move(icuFormatter));
|
||||
icuObjCache_[static_cast<int>(type)] = icuFormatter;
|
||||
}
|
||||
|
||||
void *GetIcuFormatterFromCache(IcuFormatterType type, std::string locale)
|
||||
ARK_INLINE void *GetIcuFormatterFromCache(IcuFormatterType type, std::string &locale)
|
||||
{
|
||||
auto iter = icuObjCache_.find(type);
|
||||
if (iter != icuObjCache_.end()) {
|
||||
EcmaContext::IcuFormatter icuFormatter = iter->second;
|
||||
if (icuFormatter.locale == locale) {
|
||||
return icuFormatter.icuObj;
|
||||
}
|
||||
auto &icuFormatter = icuObjCache_[static_cast<int>(type)];
|
||||
if (icuFormatter.locale == locale) {
|
||||
return icuFormatter.icuObj;
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
void ClearIcuCache()
|
||||
{
|
||||
auto iter = icuObjCache_.begin();
|
||||
while (iter != icuObjCache_.end()) {
|
||||
EcmaContext::IcuFormatter icuFormatter = iter->second;
|
||||
for (uint32_t i = 0; i < static_cast<uint32_t>(IcuFormatterType::ICU_FORMATTER_TYPE_COUNT); i++) {
|
||||
auto &icuFormatter = icuObjCache_[i];
|
||||
IcuDeleteEntry deleteEntry = icuFormatter.deleteEntry;
|
||||
if (deleteEntry != nullptr) {
|
||||
deleteEntry(icuFormatter.icuObj, vm_);
|
||||
}
|
||||
iter->second = EcmaContext::IcuFormatter{};
|
||||
iter++;
|
||||
icuFormatter = EcmaContext::IcuFormatter{};
|
||||
}
|
||||
}
|
||||
|
||||
@ -545,8 +541,7 @@ private:
|
||||
IcuFormatter(const std::string &locale, void *icuObj, IcuDeleteEntry deleteEntry = nullptr)
|
||||
: locale(locale), icuObj(icuObj), deleteEntry(deleteEntry) {}
|
||||
};
|
||||
std::unordered_map<IcuFormatterType, IcuFormatter> icuObjCache_;
|
||||
|
||||
IcuFormatter icuObjCache_[static_cast<uint32_t>(IcuFormatterType::ICU_FORMATTER_TYPE_COUNT)];
|
||||
// Handlescope
|
||||
static const uint32_t NODE_BLOCK_SIZE_LOG2 = 10;
|
||||
static const uint32_t NODE_BLOCK_SIZE = 1U << NODE_BLOCK_SIZE_LOG2;
|
||||
|
@ -20,6 +20,7 @@
|
||||
#include "ecmascript/mem/c_string.h"
|
||||
#include "ecmascript/mem/barriers-inl.h"
|
||||
#include "ecmascript/object_factory-inl.h"
|
||||
#include "ecmascript/ecma_string-inl.h"
|
||||
|
||||
#include "unicode/udata.h"
|
||||
|
||||
@ -315,9 +316,9 @@ JSHandle<JSCollator> JSCollator::InitializeCollator(JSThread *thread,
|
||||
return collator;
|
||||
}
|
||||
|
||||
icu::Collator *JSCollator::GetCachedIcuCollator(JSThread *thread, const JSHandle<JSTaggedValue> &locales)
|
||||
icu::Collator *JSCollator::GetCachedIcuCollator(JSThread *thread, const JSTaggedValue &locales)
|
||||
{
|
||||
std::string cacheEntry = locales->IsUndefined() ? "" : EcmaStringAccessor(locales.GetTaggedValue()).ToStdString();
|
||||
std::string cacheEntry = locales.IsUndefined() ? "" : EcmaStringAccessor(locales).ToStdString();
|
||||
void *cachedCollator =
|
||||
thread->GetCurrentEcmaContext()->GetIcuFormatterFromCache(IcuFormatterType::COLLATOR, cacheEntry);
|
||||
if (cachedCollator != nullptr) {
|
||||
@ -326,6 +327,11 @@ icu::Collator *JSCollator::GetCachedIcuCollator(JSThread *thread, const JSHandle
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
icu::Collator *JSCollator::GetCachedIcuCollator(JSThread *thread, const JSHandle<JSTaggedValue> &locales)
|
||||
{
|
||||
return GetCachedIcuCollator(thread, locales.GetTaggedValue());
|
||||
}
|
||||
|
||||
UColAttributeValue JSCollator::OptionToUColAttribute(CaseFirstOption caseFirstOption)
|
||||
{
|
||||
auto iter = uColAttributeValueMap.find(caseFirstOption);
|
||||
@ -455,22 +461,49 @@ JSHandle<JSObject> JSCollator::ResolvedOptions(JSThread *thread, const JSHandle<
|
||||
return options;
|
||||
}
|
||||
|
||||
icu::UnicodeString EcmaStringToUString(const JSHandle<EcmaString> &string)
|
||||
ARK_INLINE icu::UnicodeString EcmaStringToUString(EcmaString *string)
|
||||
{
|
||||
std::string stdString(ConvertToString(*string, StringConvertedUsage::LOGICOPERATION));
|
||||
icu::StringPiece sp(stdString);
|
||||
CVector<uint8_t> buf;
|
||||
Span<const uint8_t> span = EcmaStringAccessor(string).ToUtf8Span(buf);
|
||||
icu::StringPiece sp(reinterpret_cast<const char*>(span.begin()), span.size());
|
||||
icu::UnicodeString uString = icu::UnicodeString::fromUTF8(sp);
|
||||
return uString;
|
||||
}
|
||||
|
||||
icu::UnicodeString EcmaStringToUString(const JSHandle<EcmaString> &string)
|
||||
{
|
||||
return EcmaStringToUString(string.GetObject<EcmaString>());
|
||||
}
|
||||
|
||||
JSTaggedValue JSCollator::CompareStrings(const icu::Collator *icuCollator, const JSHandle<EcmaString> &string1,
|
||||
const JSHandle<EcmaString> &string2)
|
||||
{
|
||||
return CompareStrings(icuCollator, string1.GetObject<EcmaString>(), string2.GetObject<EcmaString>());
|
||||
}
|
||||
|
||||
JSTaggedValue JSCollator::CompareStrings(const icu::Collator *icuCollator, EcmaString *string1, EcmaString *string2)
|
||||
{
|
||||
UCollationResult result;
|
||||
UErrorCode status = U_ZERO_ERROR;
|
||||
if (string1 == string2) {
|
||||
return JSTaggedValue(UCollationResult::UCOL_EQUAL);
|
||||
}
|
||||
{
|
||||
EcmaStringAccessor string1Acc(string1);
|
||||
EcmaStringAccessor string2Acc(string2);
|
||||
if (string1Acc.IsUtf8() && string1Acc.IsLineOrConstantString() &&
|
||||
string2Acc.IsUtf8() && string2Acc.IsLineOrConstantString()) {
|
||||
icu::StringPiece stringPiece1(reinterpret_cast<const char*>(string1Acc.GetDataUtf8()),
|
||||
string1Acc.GetLength());
|
||||
icu::StringPiece stringPiece2(reinterpret_cast<const char*>(string2Acc.GetDataUtf8()),
|
||||
string2Acc.GetLength());
|
||||
result = icuCollator->compareUTF8(stringPiece1, stringPiece2, status);
|
||||
return JSTaggedValue(result);
|
||||
}
|
||||
}
|
||||
icu::UnicodeString uString1 = EcmaStringToUString(string1);
|
||||
icu::UnicodeString uString2 = EcmaStringToUString(string2);
|
||||
|
||||
UCollationResult result;
|
||||
UErrorCode status = U_ZERO_ERROR;
|
||||
result = icuCollator->compare(uString1, uString2, status);
|
||||
ASSERT(U_SUCCESS(status));
|
||||
|
||||
|
@ -88,6 +88,7 @@ public:
|
||||
bool enableLocaleCache = false);
|
||||
|
||||
static icu::Collator *GetCachedIcuCollator(JSThread *thread, const JSHandle<JSTaggedValue> &locales);
|
||||
static icu::Collator *GetCachedIcuCollator(JSThread *thread, const JSTaggedValue &locales);
|
||||
|
||||
// 11.3.4 Intl.Collator.prototype.resolvedOptions ()
|
||||
static JSHandle<JSObject> ResolvedOptions(JSThread *thread, const JSHandle<JSCollator> &collator);
|
||||
@ -97,6 +98,8 @@ public:
|
||||
static JSTaggedValue CompareStrings(const icu::Collator *icuCollator, const JSHandle<EcmaString> &string1,
|
||||
const JSHandle<EcmaString> &string2);
|
||||
|
||||
static JSTaggedValue CompareStrings(const icu::Collator *icuCollator, EcmaString *string1, EcmaString *string2);
|
||||
|
||||
static JSTaggedValue FastCompareStrings(JSThread *thread, const icu::Collator *icuCollator,
|
||||
const JSHandle<EcmaString> &string1,
|
||||
const JSHandle<EcmaString> &string2);
|
||||
|
@ -2784,6 +2784,31 @@ DEF_RUNTIME_STUBS(ObjectSlowAssign)
|
||||
return builtins::BuiltinsObject::AssignTaggedValue(thread, source, toAssign).GetRawData();
|
||||
}
|
||||
|
||||
DEF_RUNTIME_STUBS(LocaleCompareWithGc)
|
||||
{
|
||||
RUNTIME_STUBS_HEADER(LocaleCompareWithGc);
|
||||
JSHandle<JSTaggedValue> locales = GetHArg<JSTaggedValue>(argv, argc, 0); // 0: means the zeroth parameter
|
||||
JSHandle<EcmaString> thisHandle = GetHArg<EcmaString>(argv, argc, 1); // 1: means the first parameter
|
||||
JSHandle<EcmaString> thatHandle = GetHArg<EcmaString>(argv, argc, 2); // 2: means the second parameter
|
||||
JSHandle<JSTaggedValue> options = GetHArg<JSTaggedValue>(argv, argc, 3); // 3: means the third parameter
|
||||
bool cacheable = options->IsUndefined() && (locales->IsUndefined() || locales->IsString());
|
||||
return builtins::BuiltinsString::LocaleCompareGC(thread, locales, thisHandle, thatHandle,
|
||||
options, cacheable).GetRawData();
|
||||
}
|
||||
|
||||
JSTaggedValue RuntimeStubs::LocaleCompareNoGc(uintptr_t argGlue, JSTaggedType locales, EcmaString *thisHandle,
|
||||
EcmaString *thatHandle)
|
||||
{
|
||||
DISALLOW_GARBAGE_COLLECTION;
|
||||
auto thread = JSThread::GlueToJSThread(argGlue);
|
||||
auto collator = JSCollator::GetCachedIcuCollator(thread, JSTaggedValue(locales));
|
||||
JSTaggedValue result = JSTaggedValue::Undefined();
|
||||
if (collator != nullptr) {
|
||||
result = JSCollator::CompareStrings(collator, thisHandle, thatHandle);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
void RuntimeStubs::Initialize(JSThread *thread)
|
||||
{
|
||||
#define DEF_RUNTIME_STUB(name) kungfu::RuntimeStubCSigns::ID_##name
|
||||
|
@ -130,6 +130,7 @@ using FastCallAotEntryType = JSTaggedValue (*)(uintptr_t glue, uint32_t argc, co
|
||||
V(ComputeHashcode) \
|
||||
V(JSHClassFindProtoTransitions) \
|
||||
V(NumberHelperStringToDouble) \
|
||||
V(LocaleCompareNoGc) \
|
||||
V(StringGetStart) \
|
||||
V(StringGetEnd)
|
||||
|
||||
@ -336,7 +337,8 @@ using FastCallAotEntryType = JSTaggedValue (*)(uintptr_t glue, uint32_t argc, co
|
||||
V(LinkedHashMapComputeCapacity) \
|
||||
V(LinkedHashSetComputeCapacity) \
|
||||
V(JSObjectGrowElementsCapacity) \
|
||||
V(HClassCloneWithAddProto)
|
||||
V(HClassCloneWithAddProto) \
|
||||
V(LocaleCompareWithGc)
|
||||
|
||||
#define RUNTIME_STUB_LIST(V) \
|
||||
RUNTIME_ASM_STUB_LIST(V) \
|
||||
@ -413,6 +415,8 @@ public:
|
||||
static bool BigIntSameValueZero(JSTaggedType key, JSTaggedType other);
|
||||
static JSTaggedValue JSHClassFindProtoTransitions(JSHClass *cls, JSTaggedValue key, JSTaggedValue proto);
|
||||
static JSTaggedValue NumberHelperStringToDouble(EcmaString *str);
|
||||
static JSTaggedValue LocaleCompareNoGc(uintptr_t argGlue, JSTaggedType locales, EcmaString *thisHandle,
|
||||
EcmaString *thatHandle);
|
||||
static double TimeClip(double time);
|
||||
static double SetDateValues(double year, double month, double day);
|
||||
static void StartCallTimer(uintptr_t argGlue, JSTaggedType func, bool isAot);
|
||||
|
18
test/moduletest/stringlocalecompare/BUILD.gn
Normal file
18
test/moduletest/stringlocalecompare/BUILD.gn
Normal file
@ -0,0 +1,18 @@
|
||||
# Copyright (c) 2023 Huawei Device Co., Ltd.
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
# You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
|
||||
import("//arkcompiler/ets_runtime/test/test_helper.gni")
|
||||
|
||||
host_moduletest_action("stringlocalecompare") {
|
||||
deps = []
|
||||
}
|
16
test/moduletest/stringlocalecompare/expect_output.txt
Normal file
16
test/moduletest/stringlocalecompare/expect_output.txt
Normal file
@ -0,0 +1,16 @@
|
||||
# Copyright (c) 2023 Huawei Device Co., Ltd.
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
# You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
|
||||
-1
|
||||
1
|
||||
0
|
34
test/moduletest/stringlocalecompare/stringlocalecompare.js
Normal file
34
test/moduletest/stringlocalecompare/stringlocalecompare.js
Normal file
@ -0,0 +1,34 @@
|
||||
/*
|
||||
* Copyright (c) 2023 Huawei Device Co., Ltd.
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
/*
|
||||
* @tc.name:stringSlice
|
||||
* @tc.desc:test String.slice
|
||||
* @tc.type: FUNC
|
||||
* @tc.require: issueI5NO8G
|
||||
*/
|
||||
|
||||
let str1 = "a";
|
||||
let str2 = "c";
|
||||
print(str1.localeCompare(str2));
|
||||
|
||||
let str3 = "check";
|
||||
let str4 = "against";
|
||||
print(str3.localeCompare(str4));
|
||||
|
||||
let str5 = "abc";
|
||||
let str6 = "abc";
|
||||
print(str5.localecCompare(str6));
|
||||
|
Loading…
x
Reference in New Issue
Block a user