Coverage Report

Created: 2026-02-16 07:47

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/serenity/Userland/Libraries/LibJS/Runtime/FunctionEnvironment.cpp
Line
Count
Source
1
/*
2
 * Copyright (c) 2021, Andreas Kling <kling@serenityos.org>
3
 *
4
 * SPDX-License-Identifier: BSD-2-Clause
5
 */
6
7
#include <LibJS/Runtime/Completion.h>
8
#include <LibJS/Runtime/ECMAScriptFunctionObject.h>
9
#include <LibJS/Runtime/FunctionEnvironment.h>
10
#include <LibJS/Runtime/GlobalObject.h>
11
12
namespace JS {
13
14
JS_DEFINE_ALLOCATOR(FunctionEnvironment);
15
16
FunctionEnvironment::FunctionEnvironment(Environment* parent_environment)
17
0
    : DeclarativeEnvironment(parent_environment)
18
0
{
19
0
}
20
21
void FunctionEnvironment::visit_edges(Visitor& visitor)
22
0
{
23
0
    Base::visit_edges(visitor);
24
0
    visitor.visit(m_this_value);
25
0
    visitor.visit(m_new_target);
26
0
    visitor.visit(m_function_object);
27
0
}
28
29
// 9.1.1.3.5 GetSuperBase ( ), https://tc39.es/ecma262/#sec-getsuperbase
30
ThrowCompletionOr<Value> FunctionEnvironment::get_super_base() const
31
0
{
32
0
    VERIFY(m_function_object);
33
34
    // 1. Let home be envRec.[[FunctionObject]].[[HomeObject]].
35
0
    auto home_object = m_function_object->home_object();
36
37
    // 2. If home is undefined, return undefined.
38
0
    if (!home_object)
39
0
        return js_undefined();
40
41
    // 3. Assert: Type(home) is Object.
42
43
    // 4. Return ? home.[[GetPrototypeOf]]().
44
0
    return TRY(home_object->internal_get_prototype_of());
45
0
}
46
47
// 9.1.1.3.2 HasThisBinding ( ), https://tc39.es/ecma262/#sec-function-environment-records-hasthisbinding
48
bool FunctionEnvironment::has_this_binding() const
49
0
{
50
0
    if (this_binding_status() == ThisBindingStatus::Lexical)
51
0
        return false;
52
0
    return true;
53
0
}
54
55
// 9.1.1.3.3 HasSuperBinding ( ), https://tc39.es/ecma262/#sec-function-environment-records-hassuperbinding
56
bool FunctionEnvironment::has_super_binding() const
57
0
{
58
0
    if (this_binding_status() == ThisBindingStatus::Lexical)
59
0
        return false;
60
0
    if (!function_object().home_object())
61
0
        return false;
62
0
    return true;
63
0
}
64
65
// 9.1.1.3.4 GetThisBinding ( ), https://tc39.es/ecma262/#sec-function-environment-records-getthisbinding
66
ThrowCompletionOr<Value> FunctionEnvironment::get_this_binding(VM& vm) const
67
0
{
68
    // 1. Assert: envRec.[[ThisBindingStatus]] is not lexical.
69
0
    VERIFY(m_this_binding_status != ThisBindingStatus::Lexical);
70
71
    // 2. If envRec.[[ThisBindingStatus]] is uninitialized, throw a ReferenceError exception.
72
0
    if (m_this_binding_status == ThisBindingStatus::Uninitialized)
73
0
        return vm.throw_completion<ReferenceError>(ErrorType::ThisHasNotBeenInitialized);
74
75
    // 3. Return envRec.[[ThisValue]].
76
0
    return m_this_value;
77
0
}
78
79
// 9.1.1.3.1 BindThisValue ( V ), https://tc39.es/ecma262/#sec-bindthisvalue
80
ThrowCompletionOr<Value> FunctionEnvironment::bind_this_value(VM& vm, Value this_value)
81
0
{
82
0
    VERIFY(!this_value.is_empty());
83
84
    // 1. Assert: envRec.[[ThisBindingStatus]] is not lexical.
85
0
    VERIFY(m_this_binding_status != ThisBindingStatus::Lexical);
86
87
    // 2. If envRec.[[ThisBindingStatus]] is initialized, throw a ReferenceError exception.
88
0
    if (m_this_binding_status == ThisBindingStatus::Initialized)
89
0
        return vm.throw_completion<ReferenceError>(ErrorType::ThisIsAlreadyInitialized);
90
91
    // 3. Set envRec.[[ThisValue]] to V.
92
0
    m_this_value = this_value;
93
94
    // 4. Set envRec.[[ThisBindingStatus]] to initialized.
95
0
    m_this_binding_status = ThisBindingStatus::Initialized;
96
97
    // 5. Return V.
98
0
    return this_value;
99
0
}
100
101
}