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/global_env.h"
19 #include "ecmascript/js_locale.h"
20 #include "ecmascript/js_object.h"
21 #include "ecmascript/js_plural_rules.h"
22 #include "ecmascript/object_factory.h"
23
24 namespace panda::ecmascript::builtins {
PluralRulesConstructor(EcmaRuntimeCallInfo * argv)25 JSTaggedValue BuiltinsPluralRules::PluralRulesConstructor(EcmaRuntimeCallInfo *argv)
26 {
27 JSThread *thread = argv->GetThread();
28 [[maybe_unused]] EcmaHandleScope scope(thread);
29 EcmaVM *ecmaVm = thread->GetEcmaVM();
30 ObjectFactory *factory = ecmaVm->GetFactory();
31
32 // 1. If NewTarget is undefined, throw a TypeError exception.
33 JSHandle<JSTaggedValue> constructor = GetConstructor(argv);
34 JSHandle<JSTaggedValue> newTarget = GetNewTarget(argv);
35 if (newTarget->IsUndefined()) {
36 THROW_TYPE_ERROR_AND_RETURN(thread, "newTarget is undefined", JSTaggedValue::Exception());
37 }
38
39 // 2. Let pluralRules be ? OrdinaryCreateFromConstructor(NewTarget, "%PluralRulesPrototype%",
40 // « [[InitializedPluralRules]], [[Locale]], [[Type]], [[MinimumIntegerDigits]], [[MinimumFractionDigits]],
41 // [[MaximumFractionDigits]], [[MinimumSignificantDigits]], [[MaximumSignificantDigits]], [[RoundingType]] »).
42 JSHandle<JSPluralRules> pluralRules =
43 JSHandle<JSPluralRules>::Cast(factory->NewJSObjectByConstructor(JSHandle<JSFunction>(constructor), newTarget));
44 RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
45
46 // 3. Return ? InitializePluralRules(pluralRules, locales, options).
47 JSHandle<JSTaggedValue> locales = GetCallArg(argv, 0);
48 JSHandle<JSTaggedValue> options = GetCallArg(argv, 1);
49 JSPluralRules::InitializePluralRules(thread, pluralRules, locales, options);
50 RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
51
52 return pluralRules.GetTaggedValue();
53 }
54
SupportedLocalesOf(EcmaRuntimeCallInfo * argv)55 JSTaggedValue BuiltinsPluralRules::SupportedLocalesOf(EcmaRuntimeCallInfo *argv)
56 {
57 JSThread *thread = argv->GetThread();
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 = JSLocale::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 [[maybe_unused]] EcmaHandleScope scope(thread);
79
80 // 1. Let pr be the this value.
81 JSHandle<JSTaggedValue> thisValue = GetThis(argv);
82
83 // 2. Perform ? RequireInternalSlot(pr, [[InitializedPluralRules]]).
84 if (!thisValue->IsJSPluralRules()) {
85 THROW_TYPE_ERROR_AND_RETURN(thread, "this is not pr object", JSTaggedValue::Exception());
86 }
87
88 // 3. Let n be ? ToNumber(value).
89 double x = 0.0;
90 JSHandle<JSTaggedValue> value = GetCallArg(argv, 0);
91 JSTaggedNumber temp = JSTaggedValue::ToNumber(thread, value);
92 RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
93 x = temp.GetNumber();
94
95 // 4. Return ? ResolvePlural(pr, n).
96 JSHandle<JSPluralRules> pluralRules = JSHandle<JSPluralRules>::Cast(thisValue);
97 JSHandle<EcmaString> result = JSPluralRules::ResolvePlural(thread, pluralRules, x);
98 RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
99 return result.GetTaggedValue();
100 }
101
ResolvedOptions(EcmaRuntimeCallInfo * argv)102 JSTaggedValue BuiltinsPluralRules::ResolvedOptions(EcmaRuntimeCallInfo *argv)
103 {
104 JSThread *thread = argv->GetThread();
105 [[maybe_unused]] EcmaHandleScope scope(thread);
106
107 // 1. Let thisValue be the this value;
108 JSHandle<JSTaggedValue> thisValue = GetThis(argv);
109
110 // 2. Perform ? RequireInternalSlot(pr, [[InitializedPluralRules]]).
111 if (!thisValue->IsJSPluralRules()) {
112 THROW_TYPE_ERROR_AND_RETURN(thread, "this is not pr object", JSTaggedValue::Exception());
113 }
114
115 // 3. Let options be ! ObjectCreate(%ObjectPrototype%).
116 auto ecmaVm = thread->GetEcmaVM();
117 JSHandle<GlobalEnv> env = ecmaVm->GetGlobalEnv();
118 ObjectFactory *factory = ecmaVm->GetFactory();
119 JSHandle<JSFunction> ctor(env->GetObjectFunction());
120 JSHandle<JSObject> options(factory->NewJSObjectByConstructor(ctor));
121
122 // 4. Perform resolvedOptions
123 JSHandle<JSPluralRules> pluralRules = JSHandle<JSPluralRules>::Cast(thisValue);
124 JSPluralRules::ResolvedOptions(thread, pluralRules, options);
125 RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
126
127 // 5. Return options.
128 return options.GetTaggedValue();
129 }
130 } // namespace panda::ecmascript::builtins