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_errors.h"
17#include "ecmascript/js_array.h"
18
19namespace panda::ecmascript::builtins {
20using ErrorHelper = base::ErrorHelper;
21using ErrorType = base::ErrorType;
22// Error
23JSTaggedValue BuiltinsError::ErrorConstructor(EcmaRuntimeCallInfo *argv)
24{
25    BUILTINS_API_TRACE(argv->GetThread(), Error, ErrorConstructor);
26    return ErrorHelper::ErrorCommonConstructor(argv, ErrorType::ERROR);
27}
28
29JSTaggedValue BuiltinsError::ToString(EcmaRuntimeCallInfo *argv)
30{
31    BUILTINS_API_TRACE(argv->GetThread(), Error, ErrorToString);
32    return ErrorHelper::ErrorCommonToString(argv, ErrorType::ERROR);
33}
34
35// RangeError
36JSTaggedValue BuiltinsRangeError::RangeErrorConstructor(EcmaRuntimeCallInfo *argv)
37{
38    BUILTINS_API_TRACE(argv->GetThread(), Error, RangeErrorConstructor);
39    return ErrorHelper::ErrorCommonConstructor(argv, ErrorType::RANGE_ERROR);
40}
41
42JSTaggedValue BuiltinsRangeError::ToString(EcmaRuntimeCallInfo *argv)
43{
44    BUILTINS_API_TRACE(argv->GetThread(), Error, RangeErrorToString);
45    return ErrorHelper::ErrorCommonToString(argv, ErrorType::RANGE_ERROR);
46}
47
48// ReferenceError
49JSTaggedValue BuiltinsReferenceError::ReferenceErrorConstructor(EcmaRuntimeCallInfo *argv)
50{
51    BUILTINS_API_TRACE(argv->GetThread(), Error, ReferenceErrorConstructor);
52    return ErrorHelper::ErrorCommonConstructor(argv, ErrorType::REFERENCE_ERROR);
53}
54
55JSTaggedValue BuiltinsReferenceError::ToString(EcmaRuntimeCallInfo *argv)
56{
57    BUILTINS_API_TRACE(argv->GetThread(), Error, ReferenceErrorToString);
58    return ErrorHelper::ErrorCommonToString(argv, ErrorType::REFERENCE_ERROR);
59}
60
61// TypeError
62JSTaggedValue BuiltinsTypeError::TypeErrorConstructor(EcmaRuntimeCallInfo *argv)
63{
64    BUILTINS_API_TRACE(argv->GetThread(), Error, TypeErrorConstructor);
65    return ErrorHelper::ErrorCommonConstructor(argv, ErrorType::TYPE_ERROR);
66}
67
68JSTaggedValue BuiltinsTypeError::ToString(EcmaRuntimeCallInfo *argv)
69{
70    BUILTINS_API_TRACE(argv->GetThread(), Error, TypeErrorToString);
71    return ErrorHelper::ErrorCommonToString(argv, ErrorType::TYPE_ERROR);
72}
73
74JSTaggedValue BuiltinsTypeError::ThrowTypeError(EcmaRuntimeCallInfo *argv)
75{
76    JSThread *thread = argv->GetThread();
77    BUILTINS_API_TRACE(thread, Error, ThrowTypeError);
78    [[maybe_unused]] EcmaHandleScope handleScope(thread);
79    THROW_TYPE_ERROR_AND_RETURN(thread, "type error", JSTaggedValue::Exception());
80}
81
82// URIError
83JSTaggedValue BuiltinsURIError::URIErrorConstructor(EcmaRuntimeCallInfo *argv)
84{
85    BUILTINS_API_TRACE(argv->GetThread(), Error, URIErrorConstructor);
86    return ErrorHelper::ErrorCommonConstructor(argv, ErrorType::URI_ERROR);
87}
88
89JSTaggedValue BuiltinsURIError::ToString(EcmaRuntimeCallInfo *argv)
90{
91    BUILTINS_API_TRACE(argv->GetThread(), Error, URIErrorToString);
92    return ErrorHelper::ErrorCommonToString(argv, ErrorType::URI_ERROR);
93}
94
95// SyntaxError
96JSTaggedValue BuiltinsSyntaxError::SyntaxErrorConstructor(EcmaRuntimeCallInfo *argv)
97{
98    BUILTINS_API_TRACE(argv->GetThread(), Error, SyntaxErrorConstructor);
99    return ErrorHelper::ErrorCommonConstructor(argv, ErrorType::SYNTAX_ERROR);
100}
101
102JSTaggedValue BuiltinsSyntaxError::ToString(EcmaRuntimeCallInfo *argv)
103{
104    BUILTINS_API_TRACE(argv->GetThread(), Error, SyntaxErrorToString);
105    return ErrorHelper::ErrorCommonToString(argv, ErrorType::SYNTAX_ERROR);
106}
107
108// EvalError
109JSTaggedValue BuiltinsEvalError::EvalErrorConstructor(EcmaRuntimeCallInfo *argv)
110{
111    BUILTINS_API_TRACE(argv->GetThread(), Error, EvalErrorConstructor);
112    return ErrorHelper::ErrorCommonConstructor(argv, ErrorType::EVAL_ERROR);
113}
114
115JSTaggedValue BuiltinsEvalError::ToString(EcmaRuntimeCallInfo *argv)
116{
117    BUILTINS_API_TRACE(argv->GetThread(), Error, EvalErrorToString);
118    return ErrorHelper::ErrorCommonToString(argv, ErrorType::EVAL_ERROR);
119}
120
121// AggregateError
122JSTaggedValue BuiltinsAggregateError::AggregateErrorConstructor(EcmaRuntimeCallInfo *argv)
123{
124    JSThread *thread = argv->GetThread();
125    BUILTINS_API_TRACE(argv->GetThread(), Error, AggregateErrorConstructor);
126    [[maybe_unused]] EcmaHandleScope scope(thread);
127    EcmaVM *ecmaVm = thread->GetEcmaVM();
128    ObjectFactory *factory = ecmaVm->GetFactory();
129    const GlobalEnvConstants *globalConst = thread->GlobalConstants();
130    // 1. If NewTarget is undefined, let newTarget be the active function object; else let newTarget be NewTarget.
131    JSHandle<JSTaggedValue> constructor = GetConstructor(argv);
132    JSMutableHandle<JSTaggedValue> newTarget(thread, GetNewTarget(argv));
133    if (newTarget->IsUndefined()) {
134        newTarget.Update(constructor.GetTaggedValue());
135    }
136    JSHandle<JSTaggedValue> errors = BuiltinsBase::GetCallArg(argv, 0);
137    JSHandle<JSTaggedValue> message = BuiltinsBase::GetCallArg(argv, 1);
138    // 2. Let O be ? OrdinaryCreateFromConstructor(newTarget, "%AggregateError.prototype%", « [[ErrorData]] »).
139    JSHandle<JSObject> objValues = factory->NewJSObjectByConstructor(JSHandle<JSFunction>(constructor), newTarget);
140    RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
141    JSHandle<JSTaggedValue> taggedObj = JSHandle<JSTaggedValue>::Cast(objValues);
142    // 3. If message is not undefined, then
143    // a. Let msg be ? ToString(message).
144    // b. Let msgDesc be the PropertyDescriptor
145    // { [[Value]]: msg, [[Writable]]: true, [[Enumerable]]: false, [[Configurable]]: true }.
146    // c. Perform ! DefinePropertyOrThrow(O, "message", msgDesc).
147    JSHandle<JSTaggedValue> msgKey = globalConst->GetHandledMessageString();
148    JSHandle<JSTaggedValue> errorsKey = globalConst->GetHandledErrorsString();
149    if (!message->IsUndefined()) {
150        JSHandle<EcmaString> handleStr = JSTaggedValue::ToString(thread, message);
151        RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
152        PropertyDescriptor msgDesc(thread, JSHandle<JSTaggedValue>::Cast(handleStr), true, false, true);
153        JSTaggedValue::DefinePropertyOrThrow(thread, taggedObj, msgKey, msgDesc);
154    }
155    // InstallErrorCause
156    JSHandle<JSTaggedValue> options = BuiltinsBase::GetCallArg(argv, 2); // 2 : Third parameter
157    // If options is an Object and ? HasProperty(options, "cause") is true, then
158    //   a. Let cause be ? Get(options, "cause").
159    //   b. Perform CreateNonEnumerableDataPropertyOrThrow(O, "cause", cause).
160    if (options->IsECMAObject()) {
161        JSHandle<JSTaggedValue> causeKey = globalConst->GetHandledCauseString();
162        bool causePresent = JSTaggedValue::HasProperty(thread, options, causeKey);
163        RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
164        if (causePresent) {
165            JSHandle<JSTaggedValue> cause = JSObject::GetProperty(thread, options, causeKey).GetValue();
166            RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
167            PropertyDescriptor causeDesc(thread, cause, true, false, true);
168            JSTaggedValue::DefinePropertyOrThrow(thread, taggedObj, causeKey, causeDesc);
169        }
170    }
171    // 4. Let errorsList be ? IterableToList(errors).
172    JSHandle<JSTaggedValue> errorsList = JSObject::IterableToList(thread, errors);
173    RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
174    // 5. Perform ! DefinePropertyOrThrow(O, "errors", PropertyDescriptor { [[Configurable]]: true,
175    //    [[Enumerable]]: false, [[Writable]]: true, [[Value]]: !CreateArrayFromList(errorsList) }).
176    JSHandle<TaggedArray> errorsArray = JSArray::ToTaggedArray(thread, errorsList);
177    JSHandle<JSTaggedValue> errorsValues(JSArray::CreateArrayFromList(thread, errorsArray));
178    PropertyDescriptor msgDesc(thread, errorsValues, true, false, true);
179    JSTaggedValue::DefinePropertyOrThrow(thread, taggedObj, errorsKey, msgDesc);
180    RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
181    // 6. Return O.
182    return taggedObj.GetTaggedValue();
183}
184
185JSTaggedValue BuiltinsAggregateError::ToString(EcmaRuntimeCallInfo *argv)
186{
187    BUILTINS_API_TRACE(argv->GetThread(), Error, AggregateErrorToString);
188    return ErrorHelper::ErrorCommonToString(argv, ErrorType::AGGREGATE_ERROR);
189}
190
191// OOMError
192JSTaggedValue BuiltinsOOMError::OOMErrorConstructor(EcmaRuntimeCallInfo *argv)
193{
194    BUILTINS_API_TRACE(argv->GetThread(), Error, OOMErrorConstructor);
195    return ErrorHelper::ErrorCommonConstructor(argv, ErrorType::OOM_ERROR);
196}
197
198JSTaggedValue BuiltinsOOMError::ToString(EcmaRuntimeCallInfo *argv)
199{
200    BUILTINS_API_TRACE(argv->GetThread(), Error, OOMErrorToString);
201    return ErrorHelper::ErrorCommonToString(argv, ErrorType::OOM_ERROR);
202}
203
204// TerminationError
205JSTaggedValue BuiltinsTerminationError::TerminationErrorConstructor(EcmaRuntimeCallInfo *argv)
206{
207    BUILTINS_API_TRACE(argv->GetThread(), Error, TerminationErrorConstructor);
208    return ErrorHelper::ErrorCommonConstructor(argv, ErrorType::TERMINATION_ERROR);
209}
210
211JSTaggedValue BuiltinsTerminationError::ToString(EcmaRuntimeCallInfo *argv)
212{
213    BUILTINS_API_TRACE(argv->GetThread(), Error, TerminationErrorToString);
214    return ErrorHelper::ErrorCommonToString(argv, ErrorType::TERMINATION_ERROR);
215}
216}  // namespace panda::ecmascript::builtins
217