1 /*
2 * Copyright (c) 2021 Huawei Device Co., Ltd.
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 * http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15
16 #include "ecmascript/builtins/builtins_plural_rules.h"
17
18 #include "ecmascript/intl/locale_helper.h"
19 #include "ecmascript/global_env.h"
20 #include "ecmascript/js_plural_rules.h"
21
22 namespace panda::ecmascript::builtins {
PluralRulesConstructor(EcmaRuntimeCallInfo *argv)23 JSTaggedValue BuiltinsPluralRules::PluralRulesConstructor(EcmaRuntimeCallInfo *argv)
24 {
25 JSThread *thread = argv->GetThread();
26 BUILTINS_API_TRACE(thread, PluralRules, Constructor);
27 [[maybe_unused]] EcmaHandleScope scope(thread);
28 EcmaVM *ecmaVm = thread->GetEcmaVM();
29 ObjectFactory *factory = ecmaVm->GetFactory();
30
31 // 1. If NewTarget is undefined, throw a TypeError exception.
32 JSHandle<JSTaggedValue> constructor = GetConstructor(argv);
33 JSHandle<JSTaggedValue> newTarget = GetNewTarget(argv);
34 if (newTarget->IsUndefined()) {
35 THROW_TYPE_ERROR_AND_RETURN(thread, "newTarget is undefined", JSTaggedValue::Exception());
36 }
37
38 // 2. Let pluralRules be ? OrdinaryCreateFromConstructor(NewTarget, "%PluralRulesPrototype%",
39 // « [[InitializedPluralRules]], [[Locale]], [[Type]], [[MinimumIntegerDigits]], [[MinimumFractionDigits]],
40 // [[MaximumFractionDigits]], [[MinimumSignificantDigits]], [[MaximumSignificantDigits]], [[RoundingType]] »).
41 JSHandle<JSObject> newObject = factory->NewJSObjectByConstructor(JSHandle<JSFunction>(constructor), newTarget);
42 RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
43 JSHandle<JSPluralRules> pluralRules = JSHandle<JSPluralRules>::Cast(newObject);
44
45 // 3. Return ? InitializePluralRules(pluralRules, locales, options).
46 JSHandle<JSTaggedValue> locales = GetCallArg(argv, 0);
47 JSHandle<JSTaggedValue> options = GetCallArg(argv, 1);
48 JSPluralRules::InitializePluralRules(thread, pluralRules, locales, options);
49 RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
50
51 return pluralRules.GetTaggedValue();
52 }
53
SupportedLocalesOf(EcmaRuntimeCallInfo *argv)54 JSTaggedValue BuiltinsPluralRules::SupportedLocalesOf(EcmaRuntimeCallInfo *argv)
55 {
56 JSThread *thread = argv->GetThread();
57 BUILTINS_API_TRACE(thread, PluralRules, SupportedLocalesOf);
58 [[maybe_unused]] EcmaHandleScope scope(thread);
59
60 // 1. Let availableLocales be %PluralRules%.[[AvailableLocales]].
61 JSHandle<TaggedArray> availableLocales = JSPluralRules::GetAvailableLocales(thread);
62
63 // 2. Let requestedLocales be ? CanonicalizeLocaleList(locales).
64 JSHandle<JSTaggedValue> locales = GetCallArg(argv, 0);
65 JSHandle<TaggedArray> requestedLocales = intl::LocaleHelper::CanonicalizeLocaleList(thread, locales);
66 RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
67
68 // 3. Return ? SupportedLocales(availableLocales, requestedLocales, options).
69 JSHandle<JSTaggedValue> options = GetCallArg(argv, 1);
70 JSHandle<JSArray> result = JSLocale::SupportedLocales(thread, availableLocales, requestedLocales, options);
71 RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
72 return result.GetTaggedValue();
73 }
74
Select(EcmaRuntimeCallInfo *argv)75 JSTaggedValue BuiltinsPluralRules::Select(EcmaRuntimeCallInfo *argv)
76 {
77 JSThread *thread = argv->GetThread();
78 BUILTINS_API_TRACE(thread, PluralRules, Select);
79 [[maybe_unused]] EcmaHandleScope scope(thread);
80
81 // 1. Let pr be the this value.
82 JSHandle<JSTaggedValue> thisValue = GetThis(argv);
83
84 // 2. Perform ? RequireInternalSlot(pr, [[InitializedPluralRules]]).
85 if (!thisValue->IsJSPluralRules()) {
86 THROW_TYPE_ERROR_AND_RETURN(thread, "this is not pr object", JSTaggedValue::Exception());
87 }
88
89 // 3. Let n be ? ToNumber(value).
90 double x = 0.0;
91 JSHandle<JSTaggedValue> value = GetCallArg(argv, 0);
92 JSTaggedNumber temp = JSTaggedValue::ToNumber(thread, value);
93 RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
94 x = temp.GetNumber();
95
96 // 4. Return ? ResolvePlural(pr, n).
97 JSHandle<JSPluralRules> pluralRules = JSHandle<JSPluralRules>::Cast(thisValue);
98 JSHandle<EcmaString> result = JSPluralRules::ResolvePlural(thread, pluralRules, x);
99 RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
100 return result.GetTaggedValue();
101 }
102
ResolvedOptions(EcmaRuntimeCallInfo *argv)103 JSTaggedValue BuiltinsPluralRules::ResolvedOptions(EcmaRuntimeCallInfo *argv)
104 {
105 JSThread *thread = argv->GetThread();
106 BUILTINS_API_TRACE(thread, PluralRules, ResolvedOptions);
107 [[maybe_unused]] EcmaHandleScope scope(thread);
108
109 // 1. Let thisValue be the this value;
110 JSHandle<JSTaggedValue> thisValue = GetThis(argv);
111
112 // 2. Perform ? RequireInternalSlot(pr, [[InitializedPluralRules]]).
113 if (!thisValue->IsJSPluralRules()) {
114 THROW_TYPE_ERROR_AND_RETURN(thread, "this is not pr object", JSTaggedValue::Exception());
115 }
116
117 // 3. Let options be ! ObjectCreate(%ObjectPrototype%).
118 auto ecmaVm = thread->GetEcmaVM();
119 JSHandle<GlobalEnv> env = ecmaVm->GetGlobalEnv();
120 ObjectFactory *factory = ecmaVm->GetFactory();
121 JSHandle<JSFunction> ctor(env->GetObjectFunction());
122 JSHandle<JSObject> options(factory->NewJSObjectByConstructor(ctor));
123
124 // 4. Perform resolvedOptions
125 JSHandle<JSPluralRules> pluralRules = JSHandle<JSPluralRules>::Cast(thisValue);
126 JSPluralRules::ResolvedOptions(thread, pluralRules, options);
127 RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
128
129 // 5. Return options.
130 return options.GetTaggedValue();
131 }
132 } // namespace panda::ecmascript::builtins