Coverage Report

Created: 2025-07-04 09:33

/src/node/src/timers.cc
Line
Count
Source (jump to first uncovered line)
1
#include "timers.h"
2
#include "env-inl.h"
3
#include "node_external_reference.h"
4
#include "util-inl.h"
5
#include "v8.h"
6
7
#include <cstdint>
8
9
namespace node {
10
namespace timers {
11
12
using v8::Context;
13
using v8::Function;
14
using v8::FunctionCallbackInfo;
15
using v8::Isolate;
16
using v8::Local;
17
using v8::Number;
18
using v8::Object;
19
using v8::ObjectTemplate;
20
using v8::Value;
21
22
134k
void BindingData::SetupTimers(const FunctionCallbackInfo<Value>& args) {
23
134k
  CHECK(args[0]->IsFunction());
24
134k
  CHECK(args[1]->IsFunction());
25
134k
  auto env = Environment::GetCurrent(args);
26
27
134k
  env->set_immediate_callback_function(args[0].As<Function>());
28
134k
  env->set_timers_callback_function(args[1].As<Function>());
29
134k
}
30
31
851
void BindingData::SlowGetLibuvNow(const FunctionCallbackInfo<Value>& args) {
32
851
  double now = GetLibuvNowImpl(Realm::GetBindingData<BindingData>(args));
33
851
  args.GetReturnValue().Set(Number::New(args.GetIsolate(), now));
34
851
}
35
36
0
double BindingData::FastGetLibuvNow(Local<Object> receiver) {
37
0
  return GetLibuvNowImpl(FromJSObject<BindingData>(receiver));
38
0
}
39
40
851
double BindingData::GetLibuvNowImpl(BindingData* data) {
41
851
  return static_cast<double>(data->env()->GetNowUint64());
42
851
}
43
44
850
void BindingData::SlowScheduleTimer(const FunctionCallbackInfo<Value>& args) {
45
850
  int64_t duration =
46
850
      args[0]->IntegerValue(args.GetIsolate()->GetCurrentContext()).FromJust();
47
850
  ScheduleTimerImpl(Realm::GetBindingData<BindingData>(args), duration);
48
850
}
49
50
0
void BindingData::FastScheduleTimer(Local<Object> receiver, int64_t duration) {
51
0
  ScheduleTimerImpl(FromJSObject<BindingData>(receiver), duration);
52
0
}
53
54
850
void BindingData::ScheduleTimerImpl(BindingData* data, int64_t duration) {
55
850
  data->env()->ScheduleTimer(duration);
56
850
}
57
58
void BindingData::SlowToggleTimerRef(
59
1.69k
    const v8::FunctionCallbackInfo<v8::Value>& args) {
60
1.69k
  ToggleTimerRefImpl(Realm::GetBindingData<BindingData>(args),
61
1.69k
                     args[0]->IsTrue());
62
1.69k
}
63
64
0
void BindingData::FastToggleTimerRef(Local<Object> receiver, bool ref) {
65
0
  ToggleTimerRefImpl(FromJSObject<BindingData>(receiver), ref);
66
0
}
67
68
1.69k
void BindingData::ToggleTimerRefImpl(BindingData* data, bool ref) {
69
1.69k
  data->env()->ToggleTimerRef(ref);
70
1.69k
}
71
72
void BindingData::SlowToggleImmediateRef(
73
0
    const v8::FunctionCallbackInfo<v8::Value>& args) {
74
0
  ToggleImmediateRefImpl(Realm::GetBindingData<BindingData>(args),
75
0
                         args[0]->IsTrue());
76
0
}
77
78
0
void BindingData::FastToggleImmediateRef(Local<Object> receiver, bool ref) {
79
0
  ToggleImmediateRefImpl(FromJSObject<BindingData>(receiver), ref);
80
0
}
81
82
0
void BindingData::ToggleImmediateRefImpl(BindingData* data, bool ref) {
83
0
  data->env()->ToggleImmediateRef(ref);
84
0
}
85
86
BindingData::BindingData(Realm* realm, Local<Object> object)
87
134k
    : SnapshotableObject(realm, object, type_int) {}
88
89
bool BindingData::PrepareForSerialization(Local<Context> context,
90
0
                                          v8::SnapshotCreator* creator) {
91
  // Return true because we need to maintain the reference to the binding from
92
  // JS land.
93
0
  return true;
94
0
}
95
96
0
InternalFieldInfoBase* BindingData::Serialize(int index) {
97
0
  DCHECK_IS_SNAPSHOT_SLOT(index);
98
0
  InternalFieldInfo* info =
99
0
      InternalFieldInfoBase::New<InternalFieldInfo>(type());
100
0
  return info;
101
0
}
102
103
void BindingData::Deserialize(Local<Context> context,
104
                              Local<Object> holder,
105
                              int index,
106
0
                              InternalFieldInfoBase* info) {
107
0
  DCHECK_IS_SNAPSHOT_SLOT(index);
108
0
  v8::HandleScope scope(context->GetIsolate());
109
0
  Realm* realm = Realm::GetCurrent(context);
110
  // Recreate the buffer in the constructor.
111
0
  BindingData* binding = realm->AddBindingData<BindingData>(holder);
112
0
  CHECK_NOT_NULL(binding);
113
0
}
114
115
v8::CFunction BindingData::fast_get_libuv_now_(
116
    v8::CFunction::Make(FastGetLibuvNow));
117
v8::CFunction BindingData::fast_schedule_timers_(
118
    v8::CFunction::Make(FastScheduleTimer));
119
v8::CFunction BindingData::fast_toggle_timer_ref_(
120
    v8::CFunction::Make(FastToggleTimerRef));
121
v8::CFunction BindingData::fast_toggle_immediate_ref_(
122
    v8::CFunction::Make(FastToggleImmediateRef));
123
124
void BindingData::CreatePerIsolateProperties(IsolateData* isolate_data,
125
134k
                                             Local<ObjectTemplate> target) {
126
134k
  Isolate* isolate = isolate_data->isolate();
127
128
134k
  SetMethod(isolate, target, "setupTimers", SetupTimers);
129
134k
  SetFastMethod(
130
134k
      isolate, target, "getLibuvNow", SlowGetLibuvNow, &fast_get_libuv_now_);
131
134k
  SetFastMethod(isolate,
132
134k
                target,
133
134k
                "scheduleTimer",
134
134k
                SlowScheduleTimer,
135
134k
                &fast_schedule_timers_);
136
134k
  SetFastMethod(isolate,
137
134k
                target,
138
134k
                "toggleTimerRef",
139
134k
                SlowToggleTimerRef,
140
134k
                &fast_toggle_timer_ref_);
141
134k
  SetFastMethod(isolate,
142
134k
                target,
143
134k
                "toggleImmediateRef",
144
134k
                SlowToggleImmediateRef,
145
134k
                &fast_toggle_immediate_ref_);
146
134k
}
147
148
void BindingData::CreatePerContextProperties(Local<Object> target,
149
                                             Local<Value> unused,
150
                                             Local<Context> context,
151
134k
                                             void* priv) {
152
134k
  Realm* realm = Realm::GetCurrent(context);
153
134k
  Environment* env = realm->env();
154
134k
  BindingData* const binding_data = realm->AddBindingData<BindingData>(target);
155
134k
  if (binding_data == nullptr) return;
156
157
  // TODO(joyeecheung): move these into BindingData.
158
134k
  target
159
134k
      ->Set(context,
160
134k
            FIXED_ONE_BYTE_STRING(realm->isolate(), "immediateInfo"),
161
134k
            env->immediate_info()->fields().GetJSArray())
162
134k
      .Check();
163
164
134k
  target
165
134k
      ->Set(context,
166
134k
            FIXED_ONE_BYTE_STRING(realm->isolate(), "timeoutInfo"),
167
134k
            env->timeout_info().GetJSArray())
168
134k
      .Check();
169
134k
}
170
171
void BindingData::RegisterTimerExternalReferences(
172
0
    ExternalReferenceRegistry* registry) {
173
0
  registry->Register(SetupTimers);
174
175
0
  registry->Register(SlowGetLibuvNow);
176
0
  registry->Register(FastGetLibuvNow);
177
0
  registry->Register(fast_get_libuv_now_.GetTypeInfo());
178
179
0
  registry->Register(SlowScheduleTimer);
180
0
  registry->Register(FastScheduleTimer);
181
0
  registry->Register(fast_schedule_timers_.GetTypeInfo());
182
183
0
  registry->Register(SlowToggleTimerRef);
184
0
  registry->Register(FastToggleTimerRef);
185
0
  registry->Register(fast_toggle_timer_ref_.GetTypeInfo());
186
187
0
  registry->Register(SlowToggleImmediateRef);
188
0
  registry->Register(FastToggleImmediateRef);
189
0
  registry->Register(fast_toggle_immediate_ref_.GetTypeInfo());
190
0
}
191
192
}  // namespace timers
193
194
}  // namespace node
195
196
NODE_BINDING_CONTEXT_AWARE_INTERNAL(
197
    timers, node::timers::BindingData::CreatePerContextProperties)
198
NODE_BINDING_PER_ISOLATE_INIT(
199
    timers, node::timers::BindingData::CreatePerIsolateProperties)
200
NODE_BINDING_EXTERNAL_REFERENCE(
201
    timers, node::timers::BindingData::RegisterTimerExternalReferences)