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_boolean.h"
17#include "ecmascript/js_primitive_ref.h"
18
19namespace panda::ecmascript::builtins {
20// ecma 19.3.1.1 Boolean(value)
21JSTaggedValue BuiltinsBoolean::BooleanConstructor(EcmaRuntimeCallInfo *argv)
22{
23    BUILTINS_ENTRY_DEBUG_LOG();
24    ASSERT(argv);
25    JSThread *thread = argv->GetThread();
26    BUILTINS_API_TRACE(thread, Boolean, Constructor);
27    [[maybe_unused]] EcmaHandleScope handleScope(thread);
28    // 1. Let b be ToBoolean(value).
29    bool boolValue = GetCallArg(argv, 0)->ToBoolean();
30    // 2. If NewTarget is undefined, return b.
31    JSHandle<JSTaggedValue> newTarget = GetNewTarget(argv);
32    if (newTarget->IsUndefined()) {
33        return GetTaggedBoolean(boolValue);
34    }
35    // 3. Let O be OrdinaryCreateFromConstructor(NewTarget, "%BooleanPrototype%", [[BooleanData]] ).
36    // 5. Set the value of O's [[BooleanData]] internal slot to b.
37    ObjectFactory *factory = thread->GetEcmaVM()->GetFactory();
38    JSHandle<JSFunction> ctor = JSHandle<JSFunction>(GetConstructor(argv));
39    JSHandle<JSObject> result = factory->NewJSObjectByConstructor(ctor, newTarget);
40    // 4. ReturnIfAbrupt(O).
41    RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
42    JSTaggedValue objValue = boolValue ? JSTaggedValue::True() : JSTaggedValue::False();
43    JSPrimitiveRef::Cast(*result)->SetValue(thread, objValue);
44    // 6. Return O.
45    return result.GetTaggedValue();
46}
47
48// ecma 19.3.3 abstract operation thisBooleanValue(value)
49JSTaggedValue BuiltinsBoolean::ThisBooleanValue(JSThread *thread, JSTaggedValue value)
50{
51    BUILTINS_API_TRACE(thread, Boolean, ThisBooleanValue);
52    // 1. If Type(value) is Boolean, return value
53    if (value.IsBoolean()) {
54        return value;
55    }
56    // 2. If Type(value) is Object and value has a [[BooleanData]] internal slot, then
57    if (value.IsJSPrimitiveRef()) {
58        JSTaggedValue primitive = JSPrimitiveRef::Cast(value.GetTaggedObject())->GetValue();
59        // a. Assert: value's [[BooleanData]] internal slot is a Boolean value.
60        if (primitive.IsBoolean()) {
61            // b. Return the value of value's [[BooleanData]] internal slot.
62            return primitive;
63        }
64    }
65    [[maybe_unused]] EcmaHandleScope handleScope(thread);
66    // 3. Throw a TypeError exception.
67    THROW_TYPE_ERROR_AND_RETURN(thread, "the type can not convert to BooleanValue", JSTaggedValue::Exception());
68}
69
70// ecma 19.3.3.2 Boolean.prototype.toString ()
71JSTaggedValue BuiltinsBoolean::BooleanPrototypeToString(EcmaRuntimeCallInfo *argv)
72{
73    ASSERT(argv);
74    JSThread *thread = argv->GetThread();
75    BUILTINS_API_TRACE(thread, Boolean, BooleanPrototypeToString);
76    [[maybe_unused]] EcmaHandleScope handleScope(thread);
77    // 1. Let b be thisBooleanValue(this value).
78    JSTaggedValue thisValueToBoolean = BuiltinsBoolean::ThisBooleanValue(thread, GetThis(argv).GetTaggedValue());
79    // 2. ReturnIfAbrupt(b)
80    RETURN_EXCEPTION_IF_ABRUPT_COMPLETION(thread);
81
82    // 3. If b is true, return "true"; else return "false".
83    return thisValueToBoolean.IsTrue() ? GetTaggedString(thread, "true") : GetTaggedString(thread, "false");
84}
85
86// ecma 19.3.3.3 Boolean.prototype.valueOf ()
87JSTaggedValue BuiltinsBoolean::BooleanPrototypeValueOf(EcmaRuntimeCallInfo *argv)
88{
89    ASSERT(argv);
90    JSThread *thread = argv->GetThread();
91    BUILTINS_API_TRACE(thread, Boolean, BooleanPrototypeValueOf);
92    // 1. Return thisBooleanValue(this value).
93    return BuiltinsBoolean::ThisBooleanValue(thread, GetThis(argv).GetTaggedValue());
94}
95}  // namespace panda::ecmascript::builtins
96