• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 "builtins_relative_time_format.h"
17 
18 namespace panda::ecmascript::builtins {
RelativeTimeFormatConstructor(EcmaRuntimeCallInfo * argv)19 JSTaggedValue BuiltinsRelativeTimeFormat::RelativeTimeFormatConstructor(EcmaRuntimeCallInfo *argv)
20 {
21     JSThread *thread = argv->GetThread();
22     [[maybe_unused]] EcmaHandleScope scope(thread);
23     EcmaVM *ecmaVm = thread->GetEcmaVM();
24     JSHandle<GlobalEnv> env = ecmaVm->GetGlobalEnv();
25     ObjectFactory *factory = ecmaVm->GetFactory();
26 
27     // 1. If NewTarget is undefined, throw a TypeError exception.
28     JSHandle<JSTaggedValue> newTarget = GetNewTarget(argv);
29     if (newTarget->IsUndefined()) {
30         THROW_TYPE_ERROR_AND_RETURN(thread, "newTarget is undefined", JSTaggedValue::Exception());
31     }
32 
33     // 2. Let relativeTimeFormat be ? OrdinaryCreateFromConstructor
34     // (NewTarget, "%RelativeTimeFormatPrototype%", « [[InitializedRelativeTimeFormat]],
35     // [[Locale]], [[DataLocale]], [[Style]], [[Numeric]], [[NumberFormat]], [[NumberingSystem]], [[PluralRules]] »).
36     JSHandle<JSTaggedValue> constructor = GetConstructor(argv);
37     JSHandle<JSRelativeTimeFormat> relativeTimeFormat = JSHandle<JSRelativeTimeFormat>::Cast(
38         factory->NewJSObjectByConstructor(JSHandle<JSFunction>(constructor), newTarget));
39     RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
40 
41     // 3. Perform ? InitializeRelativeTimeFormat(relativeTimeFormat, locales, options).
42     JSHandle<JSTaggedValue> locales = GetCallArg(argv, 0);
43     JSHandle<JSTaggedValue> options = GetCallArg(argv, 1);
44     JSRelativeTimeFormat::InitializeRelativeTimeFormat(thread, relativeTimeFormat, locales, options);
45     RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
46 
47     // 4.  Intl.RelativeTimeFormat.prototype[ @@toStringTag ]
48     // This property has the attributes { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: true }.
49     JSHandle<JSTaggedValue> thisValue = GetThis(argv);
50     bool isInstanceOf = JSObject::InstanceOf(thread, thisValue, env->GetRelativeTimeFormatFunction());
51     RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
52     if (newTarget->IsUndefined() && thisValue->IsJSObject() && isInstanceOf) {
53         PropertyDescriptor descriptor(thread, JSHandle<JSTaggedValue>::Cast(relativeTimeFormat), false, false, true);
54         JSHandle<JSTaggedValue> key(thread, JSHandle<JSIntl>::Cast(env->GetIntlFunction())->GetFallbackSymbol());
55         JSTaggedValue::DefinePropertyOrThrow(thread, thisValue, key, descriptor);
56         RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
57         return thisValue.GetTaggedValue();
58     }
59 
60     return relativeTimeFormat.GetTaggedValue();
61 }
62 
SupportedLocalesOf(EcmaRuntimeCallInfo * argv)63 JSTaggedValue BuiltinsRelativeTimeFormat::SupportedLocalesOf(EcmaRuntimeCallInfo *argv)
64 {
65     JSThread *thread = argv->GetThread();
66     [[maybe_unused]] EcmaHandleScope scope(thread);
67 
68     // 1. Let availableLocales be %RelativeTimeFormat%.[[AvailableLocales]].
69     JSHandle<TaggedArray> availableLocales = JSLocale::GetAvailableLocales(thread, "calendar", nullptr);
70 
71     // 2. Let requestedLocales be ? CanonicalizeLocaleList(locales).
72     JSHandle<JSTaggedValue> locales = GetCallArg(argv, 0);
73     JSHandle<TaggedArray> requestedLocales = JSLocale::CanonicalizeLocaleList(thread, locales);
74     RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
75 
76     // 3. Return ? SupportedLocales(availableLocales, requestedLocales, options).
77     JSHandle<JSTaggedValue> options = GetCallArg(argv, 1);
78     JSHandle<JSArray> result = JSLocale::SupportedLocales(thread, availableLocales, requestedLocales, options);
79     RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
80     return result.GetTaggedValue();
81 }
82 
Format(EcmaRuntimeCallInfo * argv)83 JSTaggedValue BuiltinsRelativeTimeFormat::Format(EcmaRuntimeCallInfo *argv)
84 {
85     JSThread *thread = argv->GetThread();
86     [[maybe_unused]] EcmaHandleScope scope(thread);
87 
88     // 1. Let relativeTimeFormat be the this value.
89     JSHandle<JSTaggedValue> thisValue = GetThis(argv);
90 
91     // 2. Perform ? RequireInternalSlot(relativeTimeFormat, [[InitializedRelativeTimeFormat]]).
92     if (!thisValue->IsJSRelativeTimeFormat()) {
93         THROW_TYPE_ERROR_AND_RETURN(thread, "this is not rtf object", JSTaggedValue::Exception());
94     }
95 
96     // 3. Let value be ? ToNumber(value).
97     double x = 0.0;
98     JSHandle<JSTaggedValue> value = GetCallArg(argv, 0);
99     JSTaggedNumber temp = JSTaggedValue::ToNumber(thread, value);
100     RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
101     x = temp.GetNumber();
102 
103     // 4. Let unit be ? ToString(unit).
104     JSHandle<JSTaggedValue> unitValue = GetCallArg(argv, 1);
105     JSHandle<EcmaString> unit = JSTaggedValue::ToString(thread, unitValue);
106     RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
107 
108     // 5. Return ? FormatRelativeTime(relativeTimeFormat, value, unit).
109     JSHandle<JSRelativeTimeFormat> relativeTimeFormat = JSHandle<JSRelativeTimeFormat>::Cast(thisValue);
110     JSHandle<EcmaString> result = JSRelativeTimeFormat::Format(thread, x, unit, relativeTimeFormat);
111     RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
112     return result.GetTaggedValue();
113 }
114 
FormatToParts(EcmaRuntimeCallInfo * argv)115 JSTaggedValue BuiltinsRelativeTimeFormat::FormatToParts(EcmaRuntimeCallInfo *argv)
116 {
117     JSThread *thread = argv->GetThread();
118     [[maybe_unused]] EcmaHandleScope scope(thread);
119 
120     // 1. Let relativeTimeFormat be the this value.
121     JSHandle<JSTaggedValue> thisValue = GetThis(argv);
122 
123     // 2. Perform ? RequireInternalSlot(relativeTimeFormat, [[InitializedRelativeTimeFormat]]).
124     if (!thisValue->IsJSRelativeTimeFormat()) {
125         THROW_TYPE_ERROR_AND_RETURN(thread, "this is not rtf object", JSTaggedValue::Exception());
126     }
127 
128     // 3. Let value be ? ToNumber(value).
129     double x = 0.0;
130     JSHandle<JSTaggedValue> value = GetCallArg(argv, 0);
131     JSTaggedNumber temp = JSTaggedValue::ToNumber(thread, value);
132     RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
133     x = temp.GetNumber();
134 
135     // 4. Let unit be ? ToString(unit).
136     JSHandle<JSTaggedValue> unitValue = GetCallArg(argv, 1);
137     JSHandle<EcmaString> unit = JSTaggedValue::ToString(thread, unitValue);
138     RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
139 
140     // 5. Return ? FormatRelativeTime(relativeTimeFormat, value, unit).
141     JSHandle<JSRelativeTimeFormat> relativeTimeFormat = JSHandle<JSRelativeTimeFormat>::Cast(thisValue);
142     JSHandle<JSArray> result = JSRelativeTimeFormat::FormatToParts(thread, x, unit, relativeTimeFormat);
143     RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
144     return result.GetTaggedValue();
145 }
146 
ResolvedOptions(EcmaRuntimeCallInfo * argv)147 JSTaggedValue BuiltinsRelativeTimeFormat::ResolvedOptions(EcmaRuntimeCallInfo *argv)
148 {
149     JSThread *thread = argv->GetThread();
150     [[maybe_unused]] EcmaHandleScope scope(thread);
151 
152     // 1. Let relativeTimeFormat be the this value.
153     JSHandle<JSTaggedValue> thisValue = GetThis(argv);
154 
155     // 2. Perform ? RequireInternalSlot(relativeTimeFormat, [[InitializedRelativeTimeFormat]]).
156     if (!thisValue->IsJSRelativeTimeFormat()) {
157         THROW_TYPE_ERROR_AND_RETURN(thread, "this is not rtf object", JSTaggedValue::Exception());
158     }
159 
160     // 3. Let options be ! ObjectCreate(%ObjectPrototype%).
161     auto ecmaVm = thread->GetEcmaVM();
162     JSHandle<GlobalEnv> env = ecmaVm->GetGlobalEnv();
163     ObjectFactory *factory = ecmaVm->GetFactory();
164     JSHandle<JSTaggedValue> ctor = env->GetObjectFunction();
165     JSHandle<JSObject> options(factory->NewJSObjectByConstructor(JSHandle<JSFunction>(ctor), ctor));
166 
167     // 4. perform resolvedOptions
168     JSHandle<JSRelativeTimeFormat> relativeTimeFormat = JSHandle<JSRelativeTimeFormat>::Cast(thisValue);
169     JSRelativeTimeFormat::ResolvedOptions(thread, relativeTimeFormat, options);
170     RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
171     // 5. Return options.
172     return options.GetTaggedValue();
173 }
174 }  // namespace panda::ecmascript::builtins