14514f5e3Sopenharmony_ci/* 24514f5e3Sopenharmony_ci * Copyright (c) 2021-2024 Huawei Device Co., Ltd. 34514f5e3Sopenharmony_ci * Licensed under the Apache License, Version 2.0 (the "License"); 44514f5e3Sopenharmony_ci * you may not use this file except in compliance with the License. 54514f5e3Sopenharmony_ci * You may obtain a copy of the License at 64514f5e3Sopenharmony_ci * 74514f5e3Sopenharmony_ci * http://www.apache.org/licenses/LICENSE-2.0 84514f5e3Sopenharmony_ci * 94514f5e3Sopenharmony_ci * Unless required by applicable law or agreed to in writing, software 104514f5e3Sopenharmony_ci * distributed under the License is distributed on an "AS IS" BASIS, 114514f5e3Sopenharmony_ci * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 124514f5e3Sopenharmony_ci * See the License for the specific language governing permissions and 134514f5e3Sopenharmony_ci * limitations under the License. 144514f5e3Sopenharmony_ci */ 154514f5e3Sopenharmony_ci 164514f5e3Sopenharmony_ci#include "builtins_collator.h" 174514f5e3Sopenharmony_ci 184514f5e3Sopenharmony_ci#include "ecmascript/intl/locale_helper.h" 194514f5e3Sopenharmony_ci#include "ecmascript/js_collator.h" 204514f5e3Sopenharmony_ci#include "ecmascript/js_function.h" 214514f5e3Sopenharmony_ci 224514f5e3Sopenharmony_cinamespace panda::ecmascript::builtins { 234514f5e3Sopenharmony_ciconstexpr uint32_t FUNCTION_LENGTH_TWO = 2; 244514f5e3Sopenharmony_ci 254514f5e3Sopenharmony_ci// 11.1.2 Intl.Collator ( [ locales [ , options ] ] ) 264514f5e3Sopenharmony_ciJSTaggedValue BuiltinsCollator::CollatorConstructor(EcmaRuntimeCallInfo *argv) 274514f5e3Sopenharmony_ci{ 284514f5e3Sopenharmony_ci JSThread *thread = argv->GetThread(); 294514f5e3Sopenharmony_ci BUILTINS_API_TRACE(thread, Collator, CollatorConstructor); 304514f5e3Sopenharmony_ci [[maybe_unused]] EcmaHandleScope scope(thread); 314514f5e3Sopenharmony_ci EcmaVM *ecmaVm = thread->GetEcmaVM(); 324514f5e3Sopenharmony_ci ObjectFactory *factory = ecmaVm->GetFactory(); 334514f5e3Sopenharmony_ci 344514f5e3Sopenharmony_ci // 1. If NewTarget is undefined, let newTarget be the active function object, else let newTarget be NewTarget. 354514f5e3Sopenharmony_ci JSHandle<JSTaggedValue> constructor = GetConstructor(argv); 364514f5e3Sopenharmony_ci JSHandle<JSTaggedValue> newTarget = GetNewTarget(argv); 374514f5e3Sopenharmony_ci if (newTarget->IsUndefined()) { 384514f5e3Sopenharmony_ci newTarget = constructor; 394514f5e3Sopenharmony_ci } 404514f5e3Sopenharmony_ci // 2. Let internalSlotsList be « [[InitializedCollator]], [[Locale]], [[Usage]], [[Sensitivity]], 414514f5e3Sopenharmony_ci // [[IgnorePunctuation]], [[Collation]], [[BoundCompare]] ». 424514f5e3Sopenharmony_ci // 3. If %Collator%.[[RelevantExtensionKeys]] contains "kn", then 434514f5e3Sopenharmony_ci // a. Append [[Numeric]] as the last element of internalSlotsList. 444514f5e3Sopenharmony_ci // 4. If %Collator%.[[RelevantExtensionKeys]] contains "kf", then 454514f5e3Sopenharmony_ci // a. Append [[CaseFirst]] as the last element of internalSlotsList. 464514f5e3Sopenharmony_ci 474514f5e3Sopenharmony_ci // 5. Let collator be ? OrdinaryCreateFromConstructor(newTarget, "%CollatorPrototype%", internalSlotsList). 484514f5e3Sopenharmony_ci JSHandle<JSObject> newObject = factory->NewJSObjectByConstructor(JSHandle<JSFunction>(constructor), newTarget); 494514f5e3Sopenharmony_ci RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread); 504514f5e3Sopenharmony_ci JSHandle<JSCollator> collator = JSHandle<JSCollator>::Cast(newObject); 514514f5e3Sopenharmony_ci 524514f5e3Sopenharmony_ci // 6. Return ? InitializeCollator(collator, locales, options). 534514f5e3Sopenharmony_ci JSHandle<JSTaggedValue> locales = GetCallArg(argv, 0); 544514f5e3Sopenharmony_ci JSHandle<JSTaggedValue> options = GetCallArg(argv, 1); 554514f5e3Sopenharmony_ci JSHandle<JSCollator> result = JSCollator::InitializeCollator(thread, collator, locales, options); 564514f5e3Sopenharmony_ci RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread); 574514f5e3Sopenharmony_ci return result.GetTaggedValue(); 584514f5e3Sopenharmony_ci} 594514f5e3Sopenharmony_ci 604514f5e3Sopenharmony_ci// 11.2.2 Intl.Collator.supportedLocalesOf ( locales [ , options ] ) 614514f5e3Sopenharmony_ciJSTaggedValue BuiltinsCollator::SupportedLocalesOf(EcmaRuntimeCallInfo *argv) 624514f5e3Sopenharmony_ci{ 634514f5e3Sopenharmony_ci JSThread *thread = argv->GetThread(); 644514f5e3Sopenharmony_ci BUILTINS_API_TRACE(thread, Collator, SupportedLocalesOf); 654514f5e3Sopenharmony_ci [[maybe_unused]] EcmaHandleScope scope(thread); 664514f5e3Sopenharmony_ci // 1. Let availableLocales be %Collator%.[[AvailableLocales]]. 674514f5e3Sopenharmony_ci JSHandle<TaggedArray> availableLocales = JSCollator::GetAvailableLocales(thread); 684514f5e3Sopenharmony_ci 694514f5e3Sopenharmony_ci // 2. Let requestedLocales be ? CanonicalizeLocaleList(locales). 704514f5e3Sopenharmony_ci JSHandle<JSTaggedValue> locales = GetCallArg(argv, 0); 714514f5e3Sopenharmony_ci JSHandle<TaggedArray> requestedLocales = intl::LocaleHelper::CanonicalizeLocaleList(thread, locales); 724514f5e3Sopenharmony_ci RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread); 734514f5e3Sopenharmony_ci 744514f5e3Sopenharmony_ci // 3. Return ? SupportedLocales(availableLocales, requestedLocales, options). 754514f5e3Sopenharmony_ci JSHandle<JSTaggedValue> options = GetCallArg(argv, 1); 764514f5e3Sopenharmony_ci JSHandle<JSArray> result = JSLocale::SupportedLocales(thread, availableLocales, requestedLocales, options); 774514f5e3Sopenharmony_ci RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread); 784514f5e3Sopenharmony_ci return result.GetTaggedValue(); 794514f5e3Sopenharmony_ci} 804514f5e3Sopenharmony_ci 814514f5e3Sopenharmony_ci// 11.3.3 get Intl.Collator.prototype.compare 824514f5e3Sopenharmony_ciJSTaggedValue BuiltinsCollator::Compare(EcmaRuntimeCallInfo *argv) 834514f5e3Sopenharmony_ci{ 844514f5e3Sopenharmony_ci JSThread *thread = argv->GetThread(); 854514f5e3Sopenharmony_ci BUILTINS_API_TRACE(thread, Collator, Compare); 864514f5e3Sopenharmony_ci [[maybe_unused]] EcmaHandleScope scope(thread); 874514f5e3Sopenharmony_ci // 1. Let collator be this value. 884514f5e3Sopenharmony_ci JSHandle<JSTaggedValue> thisValue = GetThis(argv); 894514f5e3Sopenharmony_ci 904514f5e3Sopenharmony_ci // 2. Perform ? RequireInternalSlot(collator, [[InitializedCollator]]). 914514f5e3Sopenharmony_ci if (!thisValue->IsJSCollator()) { 924514f5e3Sopenharmony_ci THROW_TYPE_ERROR_AND_RETURN(thread, "this is not collator", JSTaggedValue::Exception()); 934514f5e3Sopenharmony_ci } 944514f5e3Sopenharmony_ci // 3. If collator.[[BoundCompare]] is undefined, then 954514f5e3Sopenharmony_ci // a. Let F be a new built-in function object as defined in 11.3.3.1. 964514f5e3Sopenharmony_ci // b. Set F.[[Collator]] to collator. 974514f5e3Sopenharmony_ci // c. Set collator.[[BoundCompare]] to F. 984514f5e3Sopenharmony_ci // 4. Return collator.[[BoundCompare]]. 994514f5e3Sopenharmony_ci JSHandle<JSCollator> collator = JSHandle<JSCollator>::Cast(thisValue); 1004514f5e3Sopenharmony_ci JSHandle<JSTaggedValue> boundCompare(thread, collator->GetBoundCompare()); 1014514f5e3Sopenharmony_ci if (boundCompare->IsUndefined()) { 1024514f5e3Sopenharmony_ci ObjectFactory *factory = thread->GetEcmaVM()->GetFactory(); 1034514f5e3Sopenharmony_ci JSHandle<JSIntlBoundFunction> intlBoundFunc = factory->NewJSIntlBoundFunction( 1044514f5e3Sopenharmony_ci MethodIndex::BUILTINS_COLLATOR_ANONYMOUS_COLLATOR, FUNCTION_LENGTH_TWO); 1054514f5e3Sopenharmony_ci intlBoundFunc->SetCollator(thread, collator); 1064514f5e3Sopenharmony_ci collator->SetBoundCompare(thread, intlBoundFunc); 1074514f5e3Sopenharmony_ci } 1084514f5e3Sopenharmony_ci return collator->GetBoundCompare(); 1094514f5e3Sopenharmony_ci} 1104514f5e3Sopenharmony_ci 1114514f5e3Sopenharmony_ci// 11.3.3.1 Collator Compare Functions 1124514f5e3Sopenharmony_ciJSTaggedValue BuiltinsCollator::AnonymousCollator(EcmaRuntimeCallInfo *argv) 1134514f5e3Sopenharmony_ci{ 1144514f5e3Sopenharmony_ci // A Collator compare function is an anonymous built-in function that has a [[Collator]] internal slot. 1154514f5e3Sopenharmony_ci // When a Collator compare function F is called with arguments x and y, the following steps are taken: 1164514f5e3Sopenharmony_ci JSThread *thread = argv->GetThread(); 1174514f5e3Sopenharmony_ci BUILTINS_API_TRACE(thread, Collator, AnonymousCollator); 1184514f5e3Sopenharmony_ci [[maybe_unused]] EcmaHandleScope scope(thread); 1194514f5e3Sopenharmony_ci JSHandle<JSIntlBoundFunction> intlBoundFunc = JSHandle<JSIntlBoundFunction>::Cast(GetConstructor(argv)); 1204514f5e3Sopenharmony_ci 1214514f5e3Sopenharmony_ci // 1. Let collator be F.[[Collator]]. 1224514f5e3Sopenharmony_ci JSHandle<JSTaggedValue> collator(thread, intlBoundFunc->GetCollator()); 1234514f5e3Sopenharmony_ci 1244514f5e3Sopenharmony_ci // 2. Assert: Type(collator) is Object and collator has an [[InitializedCollator]] internal slot. 1254514f5e3Sopenharmony_ci ASSERT_PRINT(collator->IsJSObject() && collator->IsJSCollator(), "collator is not object or JSCollator"); 1264514f5e3Sopenharmony_ci 1274514f5e3Sopenharmony_ci // 3. If x is not provided, let x be undefined. 1284514f5e3Sopenharmony_ci JSHandle<JSTaggedValue> x = GetCallArg(argv, 0); 1294514f5e3Sopenharmony_ci 1304514f5e3Sopenharmony_ci // 4. If y is not provided, let y be undefined. 1314514f5e3Sopenharmony_ci JSHandle<JSTaggedValue> y = GetCallArg(argv, 1); 1324514f5e3Sopenharmony_ci 1334514f5e3Sopenharmony_ci // 5. Let X be ? ToString(x). 1344514f5e3Sopenharmony_ci JSHandle<EcmaString> xValue = JSTaggedValue::ToString(thread, x); 1354514f5e3Sopenharmony_ci RETURN_VALUE_IF_ABRUPT_COMPLETION(thread, JSTaggedValue::Undefined()); 1364514f5e3Sopenharmony_ci // 6. Let Y be ? ToString(y). 1374514f5e3Sopenharmony_ci JSHandle<EcmaString> yValue = JSTaggedValue::ToString(thread, y); 1384514f5e3Sopenharmony_ci RETURN_VALUE_IF_ABRUPT_COMPLETION(thread, JSTaggedValue::Undefined()); 1394514f5e3Sopenharmony_ci // 7. Return CompareStrings(collator, X, Y). 1404514f5e3Sopenharmony_ci icu::Collator *icuCollator = (JSHandle<JSCollator>::Cast(collator))->GetIcuCollator(); 1414514f5e3Sopenharmony_ci return JSCollator::CompareStrings(thread, icuCollator, xValue, yValue); 1424514f5e3Sopenharmony_ci} 1434514f5e3Sopenharmony_ci 1444514f5e3Sopenharmony_ci// 11.3.4 Intl.Collator.prototype.resolvedOptions () 1454514f5e3Sopenharmony_ciJSTaggedValue BuiltinsCollator::ResolvedOptions(EcmaRuntimeCallInfo *argv) 1464514f5e3Sopenharmony_ci{ 1474514f5e3Sopenharmony_ci JSThread *thread = argv->GetThread(); 1484514f5e3Sopenharmony_ci BUILTINS_API_TRACE(thread, Collator, ResolvedOptions); 1494514f5e3Sopenharmony_ci [[maybe_unused]] EcmaHandleScope scope(thread); 1504514f5e3Sopenharmony_ci JSHandle<JSTaggedValue> thisValue = GetThis(argv); 1514514f5e3Sopenharmony_ci if (!thisValue->IsJSCollator()) { 1524514f5e3Sopenharmony_ci THROW_TYPE_ERROR_AND_RETURN(thread, "this is not Collator object", JSTaggedValue::Exception()); 1534514f5e3Sopenharmony_ci } 1544514f5e3Sopenharmony_ci JSHandle<JSObject> options = JSCollator::ResolvedOptions(thread, JSHandle<JSCollator>::Cast(thisValue)); 1554514f5e3Sopenharmony_ci return options.GetTaggedValue(); 1564514f5e3Sopenharmony_ci} 1574514f5e3Sopenharmony_ci} // namespace panda::ecmascript::builtins