1 /*
2 * Copyright (c) 2022 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_list_format.h"
17
18 #include "ecmascript/intl/locale_helper.h"
19 #include "ecmascript/global_env.h"
20 #include "ecmascript/js_list_format.h"
21
22 namespace panda::ecmascript::builtins {
ListFormatConstructor(EcmaRuntimeCallInfo *argv)23 JSTaggedValue BuiltinsListFormat::ListFormatConstructor(EcmaRuntimeCallInfo *argv)
24 {
25 JSThread *thread = argv->GetThread();
26 BUILTINS_API_TRACE(thread, ListFormat, 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> newTarget = GetNewTarget(argv);
33 if (newTarget->IsUndefined()) {
34 THROW_TYPE_ERROR_AND_RETURN(thread, "newTarget is undefined", JSTaggedValue::Exception());
35 }
36
37 // 2. Let listFormat be ? OrdinaryCreateFromConstructor
38 // (NewTarget, "%ListFormat.prototype%", « [[InitializedListFormat]], [[Locale]],
39 // [[Type]], [[Style]], [[Templates]] »).
40
41 JSHandle<JSTaggedValue> constructor = GetConstructor(argv);
42 JSHandle<JSObject> newObject = factory->NewJSObjectByConstructor(JSHandle<JSFunction>(constructor), newTarget);
43 RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
44 JSHandle<JSListFormat> listFormat = JSHandle<JSListFormat>::Cast(newObject);
45
46 // 3. Perform ? InitializeListFormat(listFormat, locales, options).
47 JSHandle<JSTaggedValue> locales = GetCallArg(argv, 0);
48 JSHandle<JSTaggedValue> options = GetCallArg(argv, 1);
49 listFormat = JSListFormat::InitializeListFormat(thread, listFormat, locales, options);
50 RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
51 return listFormat.GetTaggedValue();
52 }
53
54 // 13.3.2 Intl.ListFormat.supportedLocalesOf ( locales [ , options ] )
SupportedLocalesOf(EcmaRuntimeCallInfo *argv)55 JSTaggedValue BuiltinsListFormat::SupportedLocalesOf(EcmaRuntimeCallInfo *argv)
56 {
57 JSThread *thread = argv->GetThread();
58 BUILTINS_API_TRACE(thread, ListFormat, SupportedLocalesOf);
59 [[maybe_unused]] EcmaHandleScope scope(thread);
60
61 // 1. Let availableLocales be %ListFormat%.[[AvailableLocales]].
62 JSHandle<TaggedArray> availableLocales = JSListFormat::GetAvailableLocales(thread);
63
64 // 2. Let requestedLocales be ? CanonicalizeLocaleList(locales).
65 JSHandle<JSTaggedValue> locales = GetCallArg(argv, 0);
66 JSHandle<TaggedArray> requestedLocales = intl::LocaleHelper::CanonicalizeLocaleList(thread, locales);
67 RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
68
69 // 3. Return ? SupportedLocales(availableLocales, requestedLocales, options).
70 JSHandle<JSTaggedValue> options = GetCallArg(argv, 1);
71 JSHandle<JSArray> result = JSLocale::SupportedLocales(thread, availableLocales, requestedLocales, options);
72 RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
73 return result.GetTaggedValue();
74 }
75
76 // 13.4.3 Intl.ListFormat.prototype.format( list )
Format(EcmaRuntimeCallInfo *argv)77 JSTaggedValue BuiltinsListFormat::Format(EcmaRuntimeCallInfo *argv)
78 {
79 JSThread *thread = argv->GetThread();
80 BUILTINS_API_TRACE(thread, ListFormat, Format);
81 [[maybe_unused]] EcmaHandleScope scope(thread);
82
83 // 1. Let lf be the this value.
84 JSHandle<JSTaggedValue> thisValue = GetThis(argv);
85
86 // 2. Perform ? RequireInternalSlot(lf, [[InitializedListFormat]]).
87 if (!thisValue->IsJSListFormat()) {
88 THROW_TYPE_ERROR_AND_RETURN(thread, "this is not JSListFormat", JSTaggedValue::Exception());
89 }
90
91 // 3. Let stringList be ? StringListFromIterable(list).
92 JSHandle<JSTaggedValue> list = GetCallArg(argv, 0);
93 JSHandle<JSTaggedValue> listArray = JSListFormat::StringListFromIterable(thread, list);
94 RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
95
96 // 4. Return FormatList(lf, stringList).
97 JSHandle<JSListFormat> listFormat = JSHandle<JSListFormat>::Cast(thisValue);
98 JSHandle<JSArray> array = JSHandle<JSArray>::Cast(listArray);
99 JSHandle<EcmaString> result = JSListFormat::FormatList(thread, listFormat, array);
100 return result.GetTaggedValue();
101 }
102
103 // 13.4.4 Intl.ListFormat.prototype.formatToParts ( list )
FormatToParts(EcmaRuntimeCallInfo *argv)104 JSTaggedValue BuiltinsListFormat::FormatToParts(EcmaRuntimeCallInfo *argv)
105 {
106 JSThread *thread = argv->GetThread();
107 BUILTINS_API_TRACE(thread, ListFormat, FormatToParts);
108 [[maybe_unused]] EcmaHandleScope scope(thread);
109
110 // 1. Let lf be the this value.
111 JSHandle<JSTaggedValue> thisValue = GetThis(argv);
112
113 // 2. Perform ? RequireInternalSlot(lf, [[InitializedListFormat]]).
114 if (!thisValue->IsJSListFormat()) {
115 THROW_TYPE_ERROR_AND_RETURN(thread, "this is not JSListFormat", JSTaggedValue::Exception());
116 }
117
118 // 3. Let stringList be ? StringListFromIterable(list).
119 JSHandle<JSTaggedValue> list = GetCallArg(argv, 0);
120 JSHandle<JSTaggedValue> listArray = JSListFormat::StringListFromIterable(thread, list);
121 RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
122
123 // 4 Return FormatListToParts(lf, stringList).
124 JSHandle<JSListFormat> listFormat = JSHandle<JSListFormat>::Cast(thisValue);
125 JSHandle<JSArray> array = JSHandle<JSArray>::Cast(listArray);
126
127 JSHandle<JSArray> result = JSListFormat::FormatListToParts(thread, listFormat, array);
128 RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
129 return result.GetTaggedValue();
130 }
131
132 // 13.4.5 Intl.ListFormat.prototype.resolvedOptions()
ResolvedOptions(EcmaRuntimeCallInfo *argv)133 JSTaggedValue BuiltinsListFormat::ResolvedOptions(EcmaRuntimeCallInfo *argv)
134 {
135 JSThread *thread = argv->GetThread();
136 BUILTINS_API_TRACE(thread, ListFormat, ResolvedOptions);
137 [[maybe_unused]] EcmaHandleScope scope(thread);
138
139 // 1. Let lf be the this value.
140 JSHandle<JSTaggedValue> thisValue = GetThis(argv);
141
142 // 2. Perform ? RequireInternalSlot(lf, [[InitializedListFormat]]).
143 if (!thisValue->IsJSListFormat()) {
144 THROW_TYPE_ERROR_AND_RETURN(thread, "this is not JSListFormat", JSTaggedValue::Exception());
145 }
146
147 // 3 .Let options be ! OrdinaryObjectCreate(%Object.prototype%).
148 auto ecmaVm = thread->GetEcmaVM();
149 JSHandle<GlobalEnv> env = ecmaVm->GetGlobalEnv();
150 ObjectFactory *factory = ecmaVm->GetFactory();
151 JSHandle<JSFunction> ctor(env->GetObjectFunction());
152 JSHandle<JSObject> options(factory->NewJSObjectByConstructor(ctor));
153
154 // 4. For each row of Table 9, except the header row, in table order, do
155 // Let p be the Property value of the current row.
156 // Let v be the value of lf's internal slot whose name is the Internal Slot value of the current row.
157 // Assert: v is not undefined.
158 // Perform ! CreateDataPropertyOrThrow(options, p, v).
159 JSHandle<JSListFormat> listFormat = JSHandle<JSListFormat>::Cast(thisValue);
160 JSListFormat::ResolvedOptions(thread, listFormat, options);
161 RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
162
163 // 5. Return options.
164 return options.GetTaggedValue();
165 }
166 } // namespace panda::ecmascript::builtins